第三十四篇日志中提到,子类对象调用父类同名的函数时需要使用作用域标识符进行限定,这是在任何继承情况下都可以使用的普适方法。
问题引入:
考虑一种特殊的情况:子类全部或部分的基类(称为中间基类)同是继承自另一个基类(称为最底层基类),此时子类含有最底层基类成员的多个副本。如果子类对象想要访问这些副本,必须通过作用域标识符指出其访问的副本来自哪个路径:
比如上图中子类Z继承自类Y1和类Y2(中间基类),同时类Y1和类Y2又均继承自X类;Y1和Y2都存在类X的成员,也就是存在两个副本。
解决方法:
如果不希望中间基类含有最底层基类X的两个副本,可以将被继承的类声明为虚基类,即在中间类声明时将最底层基类声明为虚基类。虚基类声明的语法如下:
class
需要注意的是,virtual并不出现在子类声明中,而是针对中间基类的(即Y1和Y2)。
进行上述声明以后,从不同路径继承得到的数据和函数成员在子类中只有一个副本,子类Z的对象就可以不使用作用域标识符对最底层基类X的成员进行访问了。
例子:
下面的例子中Y1和Y2中使用virtual将X声明为虚基类:
class
声明为虚基类以后,子类就仅含有一个最底层基类的成员副本,即Z只有一个X中的fun()函数和value数据的副本。此时,Z的对象就可以直接访问fun()和value了,如下:
Z
补充:
当最底层基类X需要带参数的构造函数时,中间基类Y1和Y2的构造函数需要调用X的构造函数。同时,子类Z也需要对X、Y1和Y2的构造函数进行调用。代码如下:
class
那么,X的构造函数会被调用三次吗(Z、Y1和Y2各调用X构造函数一次)?
答案是否定的,C++中将当前对象所属的类称为最远子类,并规定只有最远子类才会调用虚基类的构造函数,不会出现虚基类的构造函数被重复调用的情况。
使用“override”声明的成员函数不能重写基类成员_C++日志(三十五)虚基类与其子类的构造函数...