C++对象模型

来源:互联网 发布:java安装失败1335 编辑:程序博客网 时间:2024/05/17 02:01

参考自http://blog.csdn.net/yang_yulei/article/details/8738802

http://blog.csdn.net/yang_yulei/article/details/8741547

原文中对象内存布局有误(图中虚表指针应在对应成员变量之前),但虚表的内容可以参考


单一继承

visual_ptr.cpp

[cpp] view plain copy
 print?
  1. class A  
  2. {  
  3. public:  
  4.     virtual int foo()  {    return  val ;    }  
  5.     virtual int funA() {}  
  6. private:  
  7.     int val ;  
  8.     char bit1 ;  
  9. } ;  
  10.   
  11. class B : public A  
  12. {  
  13. public:  
  14.     virtual int foo() {    return  bit2;    }  
  15.     virtual int funB() {}  
  16. private:  
  17.     char bit2 ;  
  18. };  
  19. int main()
  20. {
  21. A a;
  22. b b;
  23. }

clang -Xclang -fdump-record-layouts visual_ptr.cpp

结果:
a:

b:



可以看到:

先放虚表指针,然后存各个成员变量,且遵循对齐原则。


多重继承

 visual_ptr2.cpp

  1. class A  
  2. {  
  3. public:  
  4.     A() {}  
  5.     virtual ~A() {}  
  6.     virtual int foo() {   return  val ;  }  
  7.     virtual int funA() {}  
  8. private:  
  9.     int val ;  
  10.     char bit1 ;  
  11. } ;  
  12.   
  13. class B
  14. {  
  15. public:  
  16.     B() {}  
  17.     virtual ~B() {}  
  18.     virtual int foo() {   return  bit2;  }  
  19.     virtual int funB(){}  
  20. private:  
  21.     char bit2 ;  
  22. };  
  23.   
  24. class Derived : public A, public B  
  25. {  
  26. public:  
  27.     Derived() {}  
  28.     virtual ~Derived() {}  
  29.     virtual int foo() {   return  bit3;  }  
  30.     virtual int funDerived() {}  
  31. private:  
  32.     char bit3 ;  
  33. }; 
  34. int main()
  35. {
  36. A a;
  37. B b;
  38. Derived  d;
  39. }
clang -Xclang -fdump-record-layouts visual_ptr2.cpp
结果:
a:


b:


 

d:



虚继承


  1. class A  
  2. {  
  3. public:  
  4.     int a ;   
  5. } ;  
  6.   
  7. class B: virtual public A
  8. {  
  9. public:  
  10.     int b ;  
  11. };  



b:


可以看出虚继承不像一般继承那样

1.一般继承把放在顶部,把新增派生类成员放在尾部虚继承新增派生类成员放在顶部,把基类成员放在尾部。

2.虚继承会为派生类生成一个虚表指针。派生类class B部分的指针指向的虚函数表的前面增加了一项:offset(从对象的开头算起,到虚基类部分的字节数)。这是为了之后的菱形继承的派生类对象能够寻址到共享虚基类部分。

如果A中有虚函数,那么派生类对象的基类部分应该也有class A的虚表指针

0 0
原创粉丝点击