参考自http://blog.csdn.net/yang_yulei/article/details/8738802
http://blog.csdn.net/yang_yulei/article/details/8741547
原文中对象内存布局有误(图中虚表指针应在对应成员变量之前),但虚表的内容可以参考
单一继承
visual_ptr.cpp
- class A
- {
- public:
- virtual int foo() { return val ; }
- virtual int funA() {}
- private:
- int val ;
- char bit1 ;
- } ;
- class B : public A
- {
- public:
- virtual int foo() { return bit2; }
- virtual int funB() {}
- private:
- char bit2 ;
- };
- int main()
- {
- A a;
- b b;
- }
clang -Xclang -fdump-record-layouts visual_ptr.cpp
结果:
a:
b:
可以看到:
先放虚表指针,然后存各个成员变量,且遵循对齐原则。
多重继承
visual_ptr2.cpp
- class A
- {
- public:
- A() {}
- virtual ~A() {}
- virtual int foo() { return val ; }
- virtual int funA() {}
- private:
- int val ;
- char bit1 ;
- } ;
- class B
- {
- public:
- B() {}
- virtual ~B() {}
- virtual int foo() { return bit2; }
- virtual int funB(){}
- private:
- char bit2 ;
- };
- class Derived : public A, public B
- {
- public:
- Derived() {}
- virtual ~Derived() {}
- virtual int foo() { return bit3; }
- virtual int funDerived() {}
- private:
- char bit3 ;
- };
- int main()
- {
- A a;
- B b;
- Derived d;
- }
clang -Xclang -fdump-record-layouts visual_ptr2.cpp
结果:
a:
b:
d:
虚继承
- class A
- {
- public:
- int a ;
- } ;
- class B: virtual public A
- {
- public:
- int b ;
- };
b:
可以看出虚继承不像一般继承那样
1.一般继承把放在顶部,把新增派生类成员放在尾部,而虚继承是把新增派生类成员放在顶部,把基类成员放在尾部。
2.虚继承会为派生类生成一个虚表指针。派生类class B部分的指针指向的虚函数表的前面增加了一项:offset(从对象的开头算起,到虚基类部分的字节数)。这是为了之后的菱形继承的派生类对象能够寻址到共享虚基类部分。
如果A中有虚函数,那么派生类对象的基类部分应该也有class A的虚表指针