虚继承解决菱形继承的原理

简介: 虚继承解决菱形继承的原理

菱形继承的问题,是由多重继承的父类祖先是同一个父类导致的。如下面的情况:

菱形继承,会导致同名成员的二义性问题和数据冗余问题,用下面的代码来测试:

class A
{
public:
  int _a;
};
// class B : public A
class B : public A
{
public:
  int _b;
};
// class C : public A
class C : public A
{
public:
  int _c;
};
class D : public B, public C
{
public:
  int _d;
};
int main()
{
  D d;
  d.B::_a = 1;  
  d.C::_a = 2;
  d._b = 3;
  d._c = 4;
  d._d = 5;
  return 0;
}

当菱形继承不加处理的话。会导致下面的情况:同名成员的二义性问题

这种二义性问题,用下面的方式即可解决:指定类域

但是还会有下面的数据冗余问题:如下,成员 _a 占据了两份同样大空间(01和02那块内存地址) ,定义成员 d时,分别对 B和C开了一块空间,而B和C又要继承类A,所以B和C都对 _a 这个成员开了一样的空间。

当_a成员不是很大的时候,还好,但当有一群_a这样的同名成员的时候,内存开销就太大了!

虚继承解决了这个问题,它是怎么解决的呢?

用上面的 A,B,C,D类来举例子。当定义出一个D的对象 d 的时候,D中继承了成员 B和 C 的各自的成员变量_b和_c,也通过 B和 C继承了 A 的成员 _a,虚拟继承会将 _a 放在一个公共的区域,通过B和C中指针指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。

如成员 _b 前面的指针,指向的虚基表里存的 16进制的14,代表 20 个字节,这恰好是_b前面的指针起始位置距离 _a 的距离,知道这个距离后,访问的时候就能找到 _a 的位置了。

再如 _c 前面的指针,指向的虚基表里的 0c ,表示十进制的 12,这个指针的起始位置和 _a 的距离就是 12,访问的时候即可以找到了。

综上所述,在虚拟继承的时候,可以通过两个类里各自指针指向虚基表里的偏移量来计算同名成员的位置,并且内存位置是相同的,这也符合我们的认知。

虽然菱形继承有了虚拟继承来解决问题,但它的底层极其复杂,会对性能造成极大影响!

所以,虽然能解决,但尽量不要设计出菱形继承!!

相关文章
|
6天前
|
安全 程序员 编译器
【C++】继承(定义、菱形继承、虚拟继承)
【C++】继承(定义、菱形继承、虚拟继承)
15 1
|
9月前
|
安全 程序员 编译器
C++中的继承/虚继承原理
C++中的继承/虚继承原理
72 0
|
6天前
|
存储 NoSQL C++
『 C++类与对象 』多继承与虚继承
『 C++类与对象 』多继承与虚继承
|
9月前
|
存储 C++
C++中菱形继承中继承不明确问题
C++中菱形继承中继承不明确问题
52 0
|
6天前
|
C++
C++继承、多继承及菱形继承
C++继承、多继承及菱形继承
|
6天前
|
C++
【C++】:菱形继承和虚拟继承
【C++】:菱形继承和虚拟继承
42 0
|
6月前
|
存储 Cloud Native Linux
C++ 怎么解决菱形继承
C++ 怎么解决菱形继承
|
6月前
复杂的菱形继承及菱形虚拟继承(详解)
复杂的菱形继承及菱形虚拟继承(详解)
26 0
|
7月前
|
存储 安全 编译器
【C++】从0到1讲继承|复杂的菱形继承
【C++】从0到1讲继承|复杂的菱形继承
|
9月前
|
编译器 C++
菱形继承和C++相关问题
菱形继承和C++相关问题