C++的继承,多继承,虚继承的对象分布的总结
来源:互联网 发布:什么软件收二手手机 编辑:程序博客网 时间:2024/06/05 11:10
根据几篇博客C++对象模型,c++涉及继承和虚继承时的内存布局 ,C++ 对象的内存布局(上) 作了一些归纳和总结,留着备用吧。
讨论问题:
- 单继承内存布局?
- 单继承(虚继承,virtual继承)的布局?
- 多继承内存布局?
- 虚继承内存布局?
1、单继承(非虚继承)
先看单继承的例子:
#include<iostream>using namespace std;class Parent{ public: int age; Parent():age(10){} virtual void f(){cout << "Parent::f()" << endl;} virtual void g(){cout << "Parent::g()" << endl;}};class Child : public Parent{ public: int num; Child():num(6){} virtual void f(){cout << "Child::f()" << endl;} virtual void h(){cout << "Child::h()" << endl;} virtual void gc(){cout << "Child::gc()" << endl;}};class GrandChild : public Child{ public: int gpa; GrandChild() : gpa(4){} virtual void f(){cout << "GrandChild::f()" << endl;} virtual void ggc(){cout << "GrandChild::ggc()" << endl;} virtual void gc(){cout << "GrandChild::gc()" << endl;}};
单继承的内存分布:
单继承(非虚继承)基本上继承父类的 vptr,并且会将自己的类的虚函数直接添加在子类的vptr,是一种 “is A ”的关系,可以共用vptr,而且对象成员变量也相应的继承过来。
2、多继承
using namespace std;class B{ public: int ib; char cb; public: B():ib(0),cb('B') {} virtual void f() { cout << "B::f()" << endl;} virtual void Bf() { cout << "B::Bf()" << endl;}};class B1 : virtual public B{ public: int ib1; char cb1; public: B1():ib1(11),cb1('1') {} virtual void f() { cout << "B1::f()" << endl;} virtual void f1() { cout << "B1::f1()" << endl;} virtual void Bf1() { cout << "B1::Bf1()" << endl;}};class B2: virtual public B{ public: int ib2; char cb2; public: B2():ib2(12),cb2('2') {} virtual void f() { cout << "B2::f()" << endl;} virtual void f2() { cout << "B2::f2()" << endl;} virtual void Bf2() { cout << "B2::Bf2()" << endl;}};class D : public B1, public B2{ public: int id; char cd; public: D():id(100),cd('D') {} virtual void f() { cout << "D::f()" << endl;} virtual void f1() { cout << "D::f1()" << endl;} virtual void f2() { cout << "D::f2()" << endl;} virtual void Df() { cout << "D::Df()" << endl;}};
多继承的对象分布:
多继承也基本类似单继承,只不过多了几张虚函数表,位置是根据多继承声明的顺序。第一张虚表还安插自己类的虚函数。每个表后面就是继承子类的成员变量。很明显,如果多继承的基类有共同的 “基基类”,必然就有2份“基基类”成员
3、虚继承
如果上面的多继承的基类(B1,B2)虚继承B,那么分布就是如下:
从图上可以看出,多了额外的一张虚表 就是 “基基类”的虚表,虚继承是一种“has A”的关系,不是is-a关系,会保存自己的一张虚表和成员,后续派生的数据成员也是只有一份。
注意:VS上,在B1和B2的 vptr和成员之间位置,会添加虚基类指针vbptr(可能是偏移地址或者直接地址),而clang和GCC没有,其他编译器实现不清楚,有些编译器可能将虚基类的偏移地址 安插到虚函数表指针中(正偏移为虚函数,负为虚基类)
虚继承B1和B2的对象分布
这里对于虚线框处,inside object C++ model 说对于虚基类会有一个 基类表指针,指向虚基类的偏移或者虚基类的地址,这里本人在实验的时候,并没有发现 vbptr,vs似乎会生成在vptr和成员变量之间。
棕色部分根据编译器实现而定,vs上似乎会生成(放在vptr和成员变量之间),gcc和clang没有这部分。
注意:VS上,在B1和B2的 vptr和成员之间位置,会添加虚基类指针vbptr(可能是偏移地址或者直接地址),而clang和GCC没有,其他编译器实现不清楚,有些编译器可能将虚基类的偏移地址 安插到虚函数表指针中(正偏移为虚函数,负为虚基类)
测试代码:
机器在64位:指针为8bytes,而且按8bytes对齐方式
#include <iostream>using namespace std;class Base{public: virtual void f(){cout<<"Base::f()";} virtual void g(){cout<<"Base::g()";} virtual void h(){cout<<"Base::h()";} long b=1;};class Base2:virtual Base{public: virtual void f(){cout<<"Base2::f()";} virtual void g(){cout<<"Base2::g()";} virtual void gb2(){cout<<"Base2::gb2()";} long b=2;};class Base3:virtual Base{public: virtual void f(){cout<<"Base3::f()";} virtual void g(){cout<<"Base3::g()";} virtual void gb3(){cout<<"Base3::gb3()";} long b=3;};class Derive:public Base2,public Base3{public: virtual void f(){cout<<"Derive::f()";} virtual void g(){cout<<"Derive::g()";} virtual void gb4(){cout<<"Derive::gb4()";}; long b=20;};int main() { //shit 这里是有8字节对齐,int类型存放也是8字节对齐/* using Fun= void (*)(); Fun fun= nullptr; Derive d; cout<< "虚函数表地址:"<<(long *)&d<<endl; cout<<"虚表-第一个函数地址:"<<(long*)*(long*)&d<<endl; //int* b=(int*)((long*)&d+3); //b 地址(如果是int会进行补齐) long*b=(long*)&d+1; cout<<*b<<" "<<*(b+1)<<endl; long **b2=(long**)((long*)&d+2);//函数表地址 fun=(Fun)b2[0][2]; fun();*/ using Fun= void (*)(); Fun fun= nullptr; Base2 b2; long*b=(long*)&b2+3; //cout<<*b<<" "<<*(b+1)<<endl; long** f=(long**)((long*)&b2 + 4); cout<< sizeof(b2); return 0;}
- C++的继承,多继承,虚继承的对象分布的总结
- 多重继承及虚继承中对象内存的分布
- 多重继承及虚继承中对象内存的分布
- 多重继承及虚继承中对象内存的分布
- 多重继承及虚继承中对象内存的分布
- 多重继承及虚继承中对象内存的分布
- 多重继承及虚继承中对象内存的分布
- 虚继承下对象的内存分布
- c++-关于菱形继承&虚继承的问题总结
- 对象继承的简单总结
- [经验总结]多重继承及虚继承中对象内存的分布(转载)
- 【转载】多重继承及虚继承中对象内存的分布
- 【C++】虚函数和虚继承的内存分布情况
- (C++)继承、菱形继承和虚继承的那些事儿
- C++ 多继承和虚继承的内存布局
- C++虚拟继承中对象内存的分布
- javascript对象的继承
- 面对对象的继承
- JPA 深度刘宝宝剖析版
- 制作支持OS::Heat::SoftwareConfig以及ansible组件的自定义centos7镜像
- android 动画系列:插值器-Interpolator
- OpenGL 实例化 初探 之 非实例化绘制行星带
- spring boot 配置文件后缀的一个坑
- C++的继承,多继承,虚继承的对象分布的总结
- Azkaban文档
- 【eclipse高效开发】——ASTView节点详解
- Android中的Material design animation
- python中的切片和join的妙用
- python检索特定内容的文本文件2
- php语法基础(二)- get和post请求
- PHP-Function
- dss源码分析1:OSMutex