errorman

不积跬步,无以至千里
随笔 - 35, 文章 - 0, 评论 - 0, 阅读 - 9793

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

虚继承

Posted on   Clemens  阅读(26)  评论(0编辑  收藏  举报

多继承产生的冲突

当存在多基类时,看下面这个例子:

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就被成为虚基类,用来解决菱形继承带来的命名冲突和数据冗余问题。

 

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示