多继承产生的冲突
当存在多基类时,看下面这个例子:
class A
{
protected:
int a;
};
class B : public A
{
protected:
int b;
};
class C : public A
{
protected:
int c;
};
class D : public B, public C
{
public:
void setA(int a) {this->a = a;}
void setB(int b) {this->b = b;}
void setC(int c) {this->c = c;}
};
int main()
{
D d;
}
编译会报错:
error: non-static member 'a' found in multiple base-class subobjects of type 'A':
class D -> class B -> class A
class D -> class C -> class A
编译器不知道成员变量a是来自B 还是来自C。
这是一个菱形继承的问题:
为了消除这个问题,我们可以用的一个方法是在变量面前指定具体哪个类。
void setA(int a) {this->B::a = a;}
int main()
{
D d;
d.setA(9);
std::cout << d.B::a << std::endl; // 输出:9
}
当存在这种菱形继承的时候,类D拥有两套类A的成员数据,虽然可以通过添加限定符进行独立访问,但是也同样存储了两份数据占用了两份空间。
可以查看内存空间:
使用虚继承可以解决菱形继承问题。
虚继承
虚继承 是面向对象编程中的一种技术,是指一个指定的基类,在继承体系结构中,将其成员数据实例共享给也从这个基类型直接或间接派生的其它类。
我们做出修改使类B 和类C 虚继承自类A:
class A
{
public:
int a;
};
class B : public virtual A
{
public:
int b;
};
class C : public virtual A
{
public:
int c;
};
class D : public B, public C
{
public:
void setA(int a) { this->a = a; }
void setB(int b) { this->b = b; }
void setC(int c) { this->c = c; }
};
int main()
{
D d;
d.setA(9);
std::cout << d.a << std::endl;
}
我们看一下内存结构:
可以看出,实际上类D 只保留了一份类A的数据成员a。此时,类A就被成为虚基类,用来解决菱形继承带来的命名冲突和数据冗余问题。
本文来自博客园,原创作者:Clemens,转载请注明原文链接:https://www.cnblogs.com/errorman/p/17262662.html