C++多态之继承8-虚基类

来源:互联网 发布:卫生防疫厨房监控软件 编辑:程序博客网 时间:2024/05/27 14:15

在之前的文章中我们讨论了多重继承,留下了一个钻石问题,本文我们将继续讨论这个问题,给出解决问题的方法。

虚基类

通过下面的例子我们来分析钻石问题

class PoweredDevice{public:    PoweredDevice(int nPower)    {cout << "PoweredDevice: " << nPower << endl;    }}; class Scanner: public PoweredDevice{public:    Scanner(int nScanner, int nPower)        : PoweredDevice(nPower)    {cout << "Scanner: " << nScanner << endl;    }}; class Printer: public PoweredDevice{public:    Printer(int nPrinter, int nPower)        : PoweredDevice(nPower)    {cout << "Printer: " << nPrinter << endl;    }}; class Copier: public Scanner, public Printer{public:    Copier(int nScanner, int nPrinter, int nPower)        : Scanner(nScanner, nPower), Printer(nPrinter, nPower)    {    }};
如果创建一个Copier对象,默认情况下会产生2份PoweredDevice的拷贝,一个来时Printer,另外一个来自Scanner。结构如下:

int main(){    Copier cCopier(1, 2, 3);}
上面的测试结果:

PoweredDevice: 3Scanner: 1PoweredDevice: 3Printer: 2
如你所见PoweredDeivce被构造了2次。也许有时候你需要这样,但是有时候你只需要一份拷贝。为了共享一个基类,简单的方法就是派生类的继承方式上加上virtual,这就是所谓的虚基类。下面的例子会教你如何使用:

class PoweredDevice{}; class Scanner: virtual public PoweredDevice{}; class Printer: virtual public PoweredDevice{}; class Copier: public Scanner, public Printer{};
虽然只会构造一个PoweredDevice对象,但是有个疑问就是谁来负责构造它呢?答案是Copier,Copier构造函数有责任来创建PoweredDevice。因此这是Copier直接调用非相邻父类构造函数。

class PoweredDevice{public:    PoweredDevice(int nPower)    {cout << "PoweredDevice: " << nPower << endl;    }}; class Scanner: virtual public PoweredDevice{public:    Scanner(int nScanner, int nPower)        : PoweredDevice(nPower)    {cout << "Scanner: " << nScanner << endl;    }}; class Printer: virtual public PoweredDevice{public:    Printer(int nPrinter, int nPower)        : PoweredDevice(nPower)    {cout << "Printer: " << nPrinter << endl;    }}; class Copier: public Scanner, public Printer{public:    Copier(int nScanner, int nPrinter, int nPower)        : Scanner(nScanner, nPower), Printer(nPrinter, nPower), PoweredDevice(nPower)    {    }};
结果:

PoweredDevice: 3Scanner: 1Printer: 2
PoweredDevice仅仅构造了一次,我们还需要注意的一些细节问题:

首先,虚基类在非虚基类之前创建,这样确保了所有基类在他们的派生类之前被创建。

其次,Scanner和Printer的构造函数依然会调用PoweredDevice的构造函数,如果我们创建的是Copier实例,这些调用将会被忽略,因为Copier是创建PoweredDevice的责任人,而不是Scanner和Printer,但是如果我们创建Scanner或者Printer实例,virtual关键字将会被忽略,正常的继承规则将适用,对PoweredDevice的构造函数调用将起作用。

最后,如果一个类继承自一个或者多个类(这些类有虚父类),那么最底层派生类负责构造虚基类。另外,这也适用于单一继承情况:如果Copier单一继承自Printer,Printer虚拟继承自PoweredDevice,Copier依然负责构造PoweredDevice。

0 0
原创粉丝点击