C++类和对象知识点整理七----虚基类和虚继承

来源:互联网 发布:python与量化投资 编辑:程序博客网 时间:2024/05/24 03:50
25、C++虚继承和虚基类
多继承(Multiple Lnheritance)是指从多个直接基类中产生派生类的能力。多继承的派生类继承了所有父类的成员。


尽管概念上非常简单,但是多个基类的相互交织可能会带来错综复杂的设计问题,命名冲突就是不可回避的一个。


如:菱形继承
解决方法 :为了消除歧义,我们可以在成员变量前面指明它具体来自哪一个类。


b.为了解决多继承时的命名冲突和冗余数据问题,C++提出了虚继承,使得在派生类中只保留一份间接基类的成员。


在继承方式前面加上virtual关键字就是虚继承


c.虚继承目的:是让某个类做出声明,承若愿意共享它的基类。其中,这个被共享的基类就称为虚基类,在这种机制下,不论虚基类在继承体系中出现了多少次,在派生类中只包含一份虚基类的成员。


虚派生只影响从指定的虚基类的派生类中进一步派生出来的类,并不会影响派生类本身


C++标准库中的 iostream 类就是一个虚继承的实际应用案例。iostream 从 istream 和 ostream 直接继承而来,而 istream 和 ostream 又都继承自一个共同的名为 base_ios 的类,是典型的菱形继承。此时 istream 和 ostream 必须采用虚继承,否则将导致 iostream 类中保留两份 base_ios 类的成员


d.虚基类成员的可见性
因为在虚继承的最终派生类中只保留了一份虚基类的成员,所以该成员可以被直接访问,不会产生二义性。此外,如果虚基类的成员只被一条派生路径覆盖,那么仍然可以直接访问这个被覆盖的成员。但是如果该成员被两条或多条路径覆盖了,那就不能直接访问了,此时必须指明该成员属于哪个类。


以菱形继承为例,假设 A 定义了一个名为 x 的成员变量,当我们在 D 中直接访问 x 时,会有三种可能性:
如果 B 和 C 中都没有 x 的定义,那么 x 将被解析为 A 的成员,此时不存在二义性。
如果 B 或 C 其中的一个类定义了 x,也不会有二义性,派生类的 x 比虚基类的 x 优先级更高。
如果 B 和 C 中都定义了 x,那么直接访问 x 将产生二义性问题。


可以看到,使用多继承经常会出现二义性问题,必须十分小心。上面的例子是简单的,如果继承的层次再多一些,关系更复杂一些,程序员就很容易陷人迷魂阵,程序的编写、调试和维护工作都会变得更加困难,因此我不提倡在程序中使用多继承,只有在比较简单和不易出现二义性的情况或实在必要时才使用多继承,能用单一继承解决的问题就不要使用多继承。也正是由于这个原因,C++ 之后的很多面向对象的编程语言,例如 Java、C#、PHP 等,都不支持多继承。