C++ 虚继承和虚继承

C++ 虚继承和虚继承

虚继承是在多继承中为了解决冲突而技术。学术一点来说,是指一个指定的基类,在继承体系结构中,将其成员数据实例共享给也从这个基类直接或间接派生的其他类。

虚继承非常有用,可以避免多继承的歧义和多重拷贝。

为什么需要虚继承?

考虑有如下继承结构。

图源Wiki

B和C继承A,D多继承B、C,我们看以下代码。

class A {
public:
    virtual void sayHi();
};

class B :public A {
public:
    virtual void onlyB();
};

class C :public A {
public:
    virtual void onlyC();
};

class D :public B, public C {

};

到这里,可能聪明的读者已经看出来有什么问题了。如果我们对D进行实例化。

D d;
A& a = d;

这么写的话,编译器会无情的报错。例如VS2019就会说这是一种不明确的转换。没错,因为按照上面的定义,D是一个有歧义的类。因为D间接地继承了两次A(B继承了,C继承了,D又继承了B和C),所以所有的D对象就会有两个不同的由A派生的派生对象(B和C)。因此,尝试直接对其进行引用,编译器会一头雾水,这个引用到底是想指向哪个A啊?究竟是 B::A 还是 C::A ?所以这样是不对的。

当然,我们可以使用static_cast进行强制类型转换,但是这不是我们今天学习的目标。

我们可以看到,我们不需要两个A,不需要A被继承两次。我们只是需要一个层次结构来说明A、B、C、D之间的关系。假如A是职业,B是销售,C是经理,我们仅仅想表示D是一个销售经理。而不意味着D是两个A,销售经理是一种职业而不是两种职业。而且从上面这个特殊的例子来看,B和C并没有重载sayHi()这个函数,sayHi()继承到D这里仍是之前那套运作规律,所以我们也不需要两份一模一样的sayHi()。

于是,虚继承便横空出世来解决这个问题了。

虚继承

我们如果这么声明继承,

class A {
public:
    virtual void sayHi();
};

// virtual
class B :public virtual A {
public:
    virtual void onlyB();
};

class C :virtual public A {
public:
    virtual void onlyC();
};

class D :public B, public C {

};

如果在继承的类之前加上一个virtual关键词,代表该继承是虚继承。这样 B::A 和 C::A 现在是一个A了。这样,D中有且仅有一个共享的A。相当于间接派生类D直接穿透它的基类B和C,直接继承了A。这样,如果再创建A对D的引用,也不会有歧义了。因为只存在一种可以转换路径,那就是直接由A到D。

这个A就是所说的虚基类。由于虚基类是多个派生类共享的基类,因此必须明确到底谁来初始化这个虚基类。C++标准规定,由最后派生的类来初始化虚基类。因此,对于间接继承了虚继类的类,也必须能直接访问虚继承来的祖先类,能够访问其虚函数表。

例如,之前的例子当中,B和C、D的构造函数初始化列表中都可以给出虚基类的初始化,但是只能由D的构造函数执行虚基类的初始化。

原文链接: https://www.cnblogs.com/scyq/p/13040352.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    C++ 虚继承和虚继承

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/352562

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午7:36
下一篇 2023年3月2日 上午7:36

相关推荐