C++反汇编学习笔记-多重继承

来源:互联网 发布:php artisan 报错 编辑:程序博客网 时间:2024/05/22 05:05

class A{

public:

       A(){ptr= "abcdefg";};

       ~A(){};

 

       virtualvoid print(){

              printf("%s\r\n",ptr);

       }

       virtualvoid printA(){

              printf("A::%s\r\n",ptr);

       }

public:

       char*ptr;

};

 

class B:virtual public A{

public:

       B(){ptr= "BBBBBBBBBBBBBBB";bv = 0xbbbbbbbb;}

       ~B(){};

       virtualvoid print(){

              printf("B::Print[%s]\r\n",ptr);

       }

       virtualvoid printB(){

              printf("B::Print1[%s]\r\n",ptr);

       }

public:

       intbv;

};

 

class C:virtual public A{

public:

       C(){ptr= "CCCCCCCCCCCCCCCCCCC";cv =0xcccccccc;}

       ~C(){};

       virtualvoid print(){

              printf("C::[%s][%s]\r\n",ptr,ptr);

       }

       virtualvoid printC(){

              printf("C::[%s][%s]\r\n",ptr,ptr);

       }

private:

       intcv;

};

 

class D:public B,public C{

public:

       D(){v=0xdddddddd;}

       ~D(){};

       virtualvoid print(){

              printf("D::[%s][%s]\r\n",A::ptr,B::ptr);

       }

private:

       intv;

};

上面例子是虚继承那么D的内存布局

B::Vfptr

D相对于B建立的虚函数表,其中不包括A虚函数

B::BToAOfsetPtr

B对象开始到A对象实体的偏移值的地址(B::BToAOfsetPtr+4)

B::MemberVerb

B成员变量

C::Vfptr

D相对于C建立的虚函数表,其中不包括A虚函数

C::CToAOfsetPtr

B对象开始到A对象实体的偏移值的地址(C::CToAOfsetPtr+4)

C::MemberVerb

C成员变量

D::MemberVerb

D成员变量

00000000

分隔

A:Vfptr

D相对于A建立的虚函数表

A::MemberVerb

A成员变量

注:在B和C对A覆盖的函数在D中一定要覆盖否则编译提示声明不确定;子对象实体到A对象实体的偏移地址要加4,那里的内容才是正确的。

class A{

public:

       A(){ptr= "abcdefg";};

       ~A(){};

 

       virtualvoid print(){

              printf("%s\r\n",ptr);

       }

       virtualvoid printA(){

              printf("A::%s\r\n",ptr);

       }

public:

       char*ptr;

};

 

class B {

public:

       B(){ptr= "BBBBBBBBBBBBBBB"; }

       ~B(){};

       virtualvoid print(){

              printf("B::Print[%s]\r\n",ptr);

       }

       virtualvoid printB(){

              printf("B::Print1[%s]\r\n",ptr);

       }

public:

       char*ptr;

};

 

class C: public A, public B{

public:

       C(){cv=0xcccccccc;}

       ~C(){};

       virtualvoid print(){

              printf("C::[%s][%s]\r\n",A::ptr,B::ptr);

       }

       virtualvoid printC(){

              printf("C::[%s][%s]\r\n",A::ptr,B::ptr);

       }

private:

       intcv;

};

 

class D:public B,public C{

public:

       D(){v=0xdddddddd;}

       ~D(){};

       virtualvoid print(){

              printf("D::[%s][%s]\r\n",A::ptr,B::ptr);

       }

private:

       intv;

};

上面例子是虚继承那么D的内存布局:

A::Vfptr

D相对于A,C建立的虚函数表

A::MemberVerb

A成员变量

B::Vfptr

D相对于B,C建立的虚函数表

B::MemberVerb

B成员变量

C::MemberVerb

C成员变量

D::MemberVerb

D成员变量

注:当多个父类有同名成员时要指名作用域

关于析构:

类的析构函数要重设自己的虚拟函数表指针,是为了它被其它类继承时它作为一个父类,子类析构调用完后再调用它时可以屏蔽子类对自己的覆盖;因为这时子类部分的资源已经被释放,如果不重设虚拟函数表那么析构函数调用的函数如果被子类覆盖,则会调用子类的函数而不是它本身的。

原创粉丝点击