虚继承和虚基类
虚继承:在继承定义中包含了virtual关键字的继承关系;
虚基类:在虚继承体系中的通过virtual继承而来的基类,需要注意的是:class CSubClass : public virtual CBase {}; 其中CBase称之为CSubClass的虚基类,而不是说CBase就是个虚基类,因为CBase还可以不不是虚继承体系中的基类。
vs中如何查看内存布局:
. 打开“Visual Studio Command Prompt (2010)”
使用cl命令的/d1 reportAllClassLayout或reportSingleClassLayoutXXX选项。这里的reportAllClassLayout选项会打印大量相关类的信息,一般用处不大。而reportSingleClassLayoutXXX选项的XXX代表要编译的代码中类的名字(这里XXX类),打印XXX类的内存布局和虚函数表(如果代码中没有对应的类,则选项无效)。
cl [filename].cpp /d1reportSingleClassLayout[className]
【举例】test.cpp文件代码如下:
#include <iostream> using namespace std; class Base { public: int a; virtual void fcn() {}; }; class Derived : public Base { public: virtual void fcn2() {}; private: int d; void fcn3() { } }; int main() { }
查看Derived这个类的对象在内存中的布局,那么就可以用下面的命令行:
l Test.cpp /d1reportSingleClassLayoutDerived
可以看到class Derived的对象的内存布局,在派生类对象的开始包含了基类Base的对象,其中有一个虚表指针,指向的就是下面的Derived::$vftable@ (virtual function table),表中包含了Derived类中所有的虚函数。
(可以看:http://www.cnblogs.com/youxin/p/3722113.html
单一继承、多重继承:
)
内存模型
在这一小节里面我主要从他面试的几个题目中来谈谈虚继承的内存模型。
代码一:
class A { virtual void a() { } }; class A1 { virtual void a() { } }; class B : public A , virtual public A1 { }; void main() { cout<<"sizeof A: "<<sizeof(A)<<endl; cout<<"sizeof A1: "<<sizeof(A1)<<endl; cout<<"sizeof B: "<<sizeof(B)<<endl; // }
结果是:4,4,12
cl test.cpp /d1reportSingleClassLayoutB
从这个内存布局就可以看出来class A、class A1和ClassB的大小,本身class A的大小应该是1bytes的内存定位大小加上虚函数指针4bytes因为有了虚函数指针后1bytes的占位就可以取消了。所以A的大小就是4bytes,同理Class A1。对于Class B它主要是从class A和class A1(虚继承)而来,所以B里面包含有一个A和A1同时因为是需继承所以就有一个指向虚基类(A1)的vbptr指针。这里为了方便我做个图直观一点:
更多:http://blog.csdn.net/wangqiulin123456/article/details/8059536
虚函数解析:http://blog.csdn.net/wangfutao01/article/details/6472291