virtual base class。

多重継承において、菱形継承問題を避けるために、複数の経路から共有されるようにした基底クラス。

通常の菱形継承では、共通の基底クラスは継承経路ごとに別々の基底クラス部分として存在する。

class PoweredDevice
{
};
 
class Scanner : public PoweredDevice
{
};
 
class Printer : public PoweredDevice
{
};
 
class Copier : public Scanner, public Printer
{
};

この場合、CopierPoweredDeviceを2つ持つことになる。

継承リストでvirtualを付けると、その基底クラスは仮想基底クラスになる。

class PoweredDevice
{
};
 
class Scanner : virtual public PoweredDevice
{
};
 
class Printer : virtual public PoweredDevice
{
};
 
class Copier : public Scanner, public Printer
{
};

この場合、Copierの中には共有されたPoweredDeviceが1つだけ存在する。

初期化

仮想基底クラスは、最も派生したクラスが初期化を担当する。

class PoweredDevice
{
public:
    PoweredDevice(int power)
    {
    }
};
 
class Scanner : virtual public PoweredDevice
{
public:
    Scanner(int scanner, int power)
        : PoweredDevice{ power }
    {
    }
};
 
class Printer : virtual public PoweredDevice
{
public:
    Printer(int printer, int power)
        : PoweredDevice{ power }
    {
    }
};
 
class Copier : public Scanner, public Printer
{
public:
    Copier(int scanner, int printer, int power)
        : PoweredDevice{ power }, Scanner{ scanner, power }, Printer{ printer, power }
    {
    }
};

この例では、PoweredDeviceの初期化を担当するのはCopierである。
ScannerPrinterのメンバー初期化リストにあるPoweredDevice{ power }は、ScannerPrinterを単独で作るときには使われるが、Copierを作るときには無視される。

構築順

最も派生したクラスの構築では、仮想基底クラスは非仮想基底クラスより先に構築される。

注意

処理系は、共有された仮想基底クラスを見つけるために追加の管理情報を持つことがあるため、オブジェクトサイズやアクセスコストに影響することがある

関連

参考