读书人

c++ 虚函数地址,该如何解决

发布时间: 2012-03-31 13:13:26 作者: rapoo

c++ 虚函数地址
最近在看《深度探索C++对象模型》这本书,看到类继承的对象布局那里,就写了如下的代码来玩玩看

C/C++ code
#include<stdio.h>#include<string.h>class Person{public:    Person(char *name, int age);    ~Person();public:    char * GetName() const {return (char*)&this->m_name;}    int GetAge() const {return this->m_age;}    virtual void Say();protected:    char m_name[20];    int m_age;};Person::Person(char *name, int age){    strcpy(this->m_name, name);    this->m_age = age;}Person::~Person(){    //}void Person::Say(){    printf("My name is %s, I'm %d this year.\n", this->m_name, this->m_age);}//////////////////////////////////////////////////////////////////////////class Student : public Person{public:    Student(char *name, int age, int id);    ~Student();public:    virtual void Say();protected:    int m_id;};Student::Student(char *name, int age, int id)        : Person(name, age){    this->m_id = id;}Student::~Student(){}void Student::Say(){    printf("I am a student by the name of %s, I'm %d, my id is %d.\n",        this->m_name, this->m_age, this->m_id);}int main(){    Person pa("pa", 12);    Student s("st", 20, 2008);    Person *ps = &s;    pa.Say();    s.Say();    ps->Say();    printf("&pa:%0x\n", &pa);    printf(" &s:%0x\n", &s);    printf(" ps:%0x\n", ps);    printf("pa.say:%0x\n", pa.Say);    printf(" s.say:%0x\n", s.Say);    printf("ps.say:%0x\n", ps->Say);    return 0;}

代码输出如下:
My name is pa, I'm 12 this year.
I am a student by the name of st, I'm 20, my id is 2008.
I am a student by the name of st, I'm 20, my id is 2008.
&pa:12ff58
&s:12ff38
ps:12ff38
pa.say:401028
s.say:401028
ps.say:401028
Press any key to continue
关于获取类对象的Say()虚函数地址那种写法,我知道是错的,问题是
printf("pa.say:%0x\n", pa.Say);
printf(" s.say:%0x\n", s.Say);
printf("ps.say:%0x\n", ps->Say);
这几句的输出内容让我很迷惑,究竟它输出的数字401028是不是没有什么意义的,知道的请说一下,这几句的汇编代码如下所示:
Assembly code
0040EE8D   push        offset @ILT+35(`vcall') (00401028)0040EE92   push        offset string "pa.say:%0x\n" (004260a0)0040EE97   call        printf (004014c0)0040EE9C   add         esp,80040EE9F   push        offset @ILT+35(`vcall') (00401028)0040EEA4   push        offset string " s.say:%0x\n" (00426094)0040EEA9   call        printf (004014c0)0040EEAE   add         esp,80040EEB1   push        offset @ILT+35(`vcall') (00401028)0040EEB6   push        offset string "ps.say:%0x\n" (00425084)0040EEBB   call        printf (004014c0)0040EEC0   add         esp,8

00401028处的内容为:
Assembly code
00401028  E9 83 00 00 00 CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC  ...烫烫烫烫烫烫烫.0040103C  CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC  烫烫烫烫烫烫烫烫烫烫00401050  55 8B EC 83 EC 44 53 56 57 51 8D 7D BC B9 11 00 00 00 B8 CC  UDSVWQ脊....柑00401064  CC CC CC F3 AB 59 89 4D FC 8B 45 FC C7 00 1C 50 42 00 8B 4D  烫腆E..PB.00401078  08 51 8B 55 FC 83 C2 04 52 E8 0A 03 00 00 83 C4 08 8B 45 FC  .Q..R.......


[解决办法]
printf("pa.say:%0x\n", pa.Say);
本身用printf输出一个函数名就没意义了。
[解决办法]
不符合语法!
------解决方案--------------------


printf("%0x,\n",*(int*)((int*)ps)[0]);
这个才是虚函数的地址
你那个不符合语法,标准禁止这么做
成员函数指针并不是一个函数指针,他代表两层含义,对于非虚的成员函数代表函数的地址,对于虚函数代表vtable中得索引值,这些在深度探索里面讲得比较清楚
[解决办法]
vtable的地址吧,如果有多个虚函数,会通过[1]取下一个虚函数地址。

读书人网 >C++

热点推荐