C++ Primer 5th笔记(chap 18 大型程序工具)虚继承

Posted thefist11

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ Primer 5th笔记(chap 18 大型程序工具)虚继承相关的知识,希望对你有一定的参考价值。

1. 问题

派生类可以多次继承同一个类。 派生类可以通过它的两个直接基类分别继承同一个间接基类, 也可以直接继承某个基类, 然后通过另一个基类再一次间接继承该类。如果某个类在派生过程中出现了多次, 则派生类中将包含该类的多个子对象。

2. 虚基类virtual inheritance

虚继承的目的是令某个类做出声明,承诺愿意共享它的基类。其中共享的基类子对象被称为虚基类,不论虚基类在继承体系下被继承多少次,在派生类中都只包含唯一一个共享的虚基类子对象(菱形继承)。

2.1 使用方式

指定虚基类的方式是在派生列表中添加关键字virtual:

//public和virtual的顺序随意
class Raccon : public virtual ZooAnimal;
class Bear : virtual public ZooAnimal;
class Panda : public Raccon,public Bear, public Endangered;

2.2 支持向基类的常规类型转换

不论基类是不是虚基类, 派生类对象都能被可访问基类的指针或引用操作

void dance(const Bear &);
void rummage(const Raccoons);
ostreamS operator  << (ostreamS, const ZooAnimal&);
Panda ying_yang;
dance(ying_yang);//正确:把一个 Panda 对象当成 Bear 传递
rummage(ying_yang)//正确:把一个 Panda 对象当成 Raccoon 传递
cout << ying_yang;//正确:把一个 Panda 对象当成 ZooAnimal 传递

2.3 虚基类成员的可见性(二义性问题)

因为在每个共享的虚基类中只有唯一一个共享的子对象, 所以该基类的成员可以被直接访问, 并且不会产生二义性。

如果虚基类的成员只被一条派生路径覆盖, 则我们仍然可以直接访问这个被覆盖的成员。 但是如果成员被多余一个基类覆盖, 则一般情况下派生类必须为该成员自定义一个新的版本

与非虚的多重继承体系一样, 解决二义性最好的方法是在派生类中为成员自定义新的实例。

eg. 假定类 B 定义了一个名为 x 的成员, D1 和 D2 都是从 B 虚继承得到的, D 继承了 D1 和 D2, 则在 D 的作用域中, x 通过 D 的两个基类都是可见的。 如果我们通过 D的对象使用 X, 有三种可能性:

  • 如 果 在 D1 和 D2 中都没有 x 的定义, 则 x 将被解析为 B 的成员, 此时不存在二义性, 一个 D 的对象只含有 x 的一个实例。
  • 如果 x 是 B 的成员, 同时是 D1 和 D2 中某一个的成员, 则同样没有二义性, 派生类的 x 比共享虚基类 B 的 x 优先级更高。
  • 如 果 在 D1 和 D2 中都有 x 的定义, 则直接访问 x 将产生二义性问题。

以上是关于C++ Primer 5th笔记(chap 18 大型程序工具)虚继承的主要内容,如果未能解决你的问题,请参考以下文章

C++ Primer 5th笔记(chap 18 大型程序工具)noexcept

C++ Primer 5th笔记(chap 18 大型程序工具)异常处理

C++ Primer 5th笔记(chap 18 大型程序工具)捕获异常

C++ Primer 5th笔记(chap 18 大型程序工具)命名空间特性

C++ Primer 5th笔记(chap 18 大型程序工具) 重载与命名空间

C++ Primer 5th笔记(chap 18 大型程序工具)构造函数与虚继承