C++:13.多重继承(菱形继承),虚继承,虚基类

多重继承:

就是一个派生类多个基类,几乎与单继承是一致的。

唯一考点:
菱形继承结构(B类C类继承A类,D类继承A类。),产生问题,派生类有多份基类的数据。   解决办法:B C都采用虚继承,只有一个虚继承也无法解决该问题。

虚继承:

厉害了,virtual不仅可以声明虚函数,还可以设定继承方式:虚继承         

被采用虚继承的基类 A,称为虚基类

此时派生类的大小扩大:会有虚基类指针B,C都会产生一个虚基类指针 vbptr(virtual base ptr)。并且如果基类有虚函数,所以派生类还会有虚函数指针vfptr。

重点:

正常继承,派生类对象的内存先放:   基类对象,再放自己的成员变量。   并且这个是派生类包含着基类内容
而虚继承,派生类对象的内存先放 :   一个虚基类指针vbptr、和自己的成员变量,之后放基类对象。          这两个却是并列存放的。所以A的am就是D自己的了,需要D自己构造

将B,C相同继承下来的A,放到最后面,在原来的地方会留下虚基类指针。b一个 c一个,还有个虚基类表(第一行 存放的是虚基类指针自己的偏移地址,一般是0. 第二行存放的是,虚基类指针到A成员变量的偏移地址),存放的是A成员变量的偏移量,用这个指针可以找到A的成员变量。

举个栗子:

class A
{
public:
	A(int data) :ma(data){ cout << "A()" << endl; }
	~A(){ cout << "~A()" << endl; }
protected:
	int ma;
};

class B : virtual public A  就在这!!!!!!!!!!!
{
public:
	B(int data) :A(data), mb(data){ cout << "B()" << endl; }
	~B(){ cout << "~B()" << endl; }
protected:
	int mb;
};

class C : virtual public A  就在这!!!!!!!!!!!
{
public:
	C(int data) :A(data), mc(data){ cout << "C()" << endl; }
	~C(){ cout << "~C()" << endl; }
protected:
	int mc;
};

class D : public B, public C
{
public:
	D(int data) :md(data),A(data), B(data), C(data)
	{
		cout << "D()" << endl;
	}
	~D(){ cout << "~D()" << endl; }
	void show(){ cout << ma << endl; }
	
protected:
	int md;
};

int main()
{
	cout << sizeof(D) << endl;
	D d(10);
	d.show();

	int *p = (int*)&d;  将B的vbptr地址给了p
	int *q = (int*)*p;  将vbptr解引用也就是B的vbtable。
	q += 1;             +1后就指向了偏移量
	int offset = *q;    记录姐引用后的偏移量

	char *p1 = (char*)&d;换成char才可以
	p1 += offset;       加上偏移量,之后p1就指向ma
	*(int*)p1 = 30;     更改ma的值

	d.show();

	return 0;
}

附一篇博客从内存布局看虚基类,挺详细的:https://blog.csdn.net/xiejingfa/article/details/48028491

猜你喜欢

转载自blog.csdn.net/qq_41214278/article/details/84071380