博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
c++虚拟继承
阅读量:4154 次
发布时间:2019-05-25

本文共 2608 字,大约阅读时间需要 8 分钟。

先看下代码:

struct A{    A(int v=100):X(v){};    virtual void foo(void){}    int X;}; struct B :virtual public A{    B(int v=10):Y(v),A(100){};    virtual void fooB(void){}    int Y;}; struct C : virtual public A{    C(int v=20):Z(v),A(100){}    virtual void fooC(void){}    int Z;};  struct D : public B, public C{    D(int v =40):B(10),C(20),A(100),L(v){}    virtual void fooD(void){}    int L;};  int _tmain(int argc, _TCHAR* argv[]){       A a;    int *ptr;    ptr = (int*)&a;    cout << ptr << " sizeof = " << sizeof(a) <

如果B虚拟继承A,则B的对象中要增加一个虚拟基类指针,其指向的表的第二项,即从本指针到虚拟基类的偏移。

例如,对象b,的虚拟基类的地址是120+8 = 128

虚拟基类在b对象的最后。

多重继承,继承n个类,有n个续表指针;包括n个虚基类,有n个虚基类指针。

举个例子,

B虚继承A,如果A中有虚函数,则B类对象的开始位置是虚表指针,第二个位置是虚基类的指针。

class A{public:    A():a(1){}    int a;};class B: public virtual A{public:    B():b(2){}    int b;};int main() {    B* b = new B;    A* a = dynamic_cast
(b); if(a == b)//b先默认转为A*,所以相等 { std::cout << "equal" << std::endl; } else { std::cout << "not equal" << std::endl; }//输出equal if (int(b) == int(a)) { std::cout << "equal" << std::endl; } else { std::cout << "not equal" << std::endl; }//输出not equal typedef void (*pFun)(void); int **ptb = (int **)b; cout<
<<" "<
<
<
output:

equal

not equal
0 8
00701E5C
00701E60
-------
00701E60
00701E58

对象b的内存分布是:

虚基类的地址是 58+8 = 60

a为什么不等于b?

a指向了60的地址,而b指向的还是58

如果在虚继承的继承上又有多态重载?

class A{public:    virtual void fun1()    {        cout<<"A"<
(b); if(a == b) { std::cout << "equal" << std::endl; } else { std::cout << "not equal" << std::endl; }//输出equal if (int(b) == int(a)) { std::cout << "equal" << std::endl; } else { std::cout << "not equal" << std::endl; }//输出not equal cout<
<

output:

equal

not equal
24
first vtb
B:fun2
-4 12
2
0
second vtb
B:fun1
1
-------
00360A18
00360A08

08 vftable ---->B:fun2()

0c   base_psb---->-4,12

10 B:b

14 0//不知道为什么为0?

18 vftable------>B:fun1()

1c A:a

如果B类变为

class B: virtual public A

{
public:
    B():b(2){}
    virtual void fun1()
    {
        cout<<"B:fun1"<<endl;
    }
    void fun2()
    {
        cout<<"B:fun2"<<endl;
    }
    int b;
};

fun2不是虚函数,所以对象b的开始不是虚函数表指针,而是虚基类指针

 pFun pfun;

   
    cout<<ptb[0][0]<<" "<<ptb[0][1]<<endl;
    
  
   
    cout<<((int*)ptb)[1]<<endl;//B:b
    
     pfun =(pFun) ptb[3][0];
     pfun();
    /*cout<<(int)ptb[3]<<endl;
    pfun = (pFun)ptb[4][0];
    cout<<"second vtb"<<endl;
    pfun();*/
  
    cout<<((int*)ptb)[4]<<endl;//A:a
    cout<<"-------"<<endl;
    cout<<a<<endl<<b<<endl;

output:

equal

not equal
20
0 12
2
B:fun1
1
-------
004D3DB4
004D3DA8

同样,为什么第2项为0?

转载地址:http://ipeti.baihongyu.com/

你可能感兴趣的文章
map server
查看>>
MTK Android 开发笔记
查看>>
大一大二ACM训练时,建立的一个博客,专门用来写题解的
查看>>
读书笔记(会不断更新中)
查看>>
图形学实验一:bresenham算法 画线和画圆
查看>>
codeblocks配置GLUT
查看>>
矩阵卷积、矩阵相乘的转化
查看>>
图形学实验二:画个火柴人
查看>>
openGL光照(illumination)
查看>>
C++重载,重写,重定义
查看>>
全排列生成算法之字典序
查看>>
在CodeBlocks中使用openGL
查看>>
CodeBlocks配置openGL遇到的一些问题
查看>>
图形学实验三:Texture Mapping
查看>>
安卓环境搭建及虚拟机genymotion使用
查看>>
Github学习
查看>>
可视化实验一:Echars的初步使用
查看>>
人机交互实验:Android开发之人物移动、地图滑动、传感器、触屏的应用
查看>>
在人机交互实验中遇到的一些问题
查看>>
可视化实验2——用D3做图表
查看>>