multiple inheritance。

1つの派生クラスが、複数の基底クラスを同時に継承すること。

基本構文

class Teacher : public Person, public Employee
{
};

このように、基底クラスをカンマ区切りで複数指定する。

class Person
{
};
 
class Employee
{
};
 
class Teacher : public Person, public Employee
{
};

この例では、TeacherPersonでもあり、Employeeでもある。

ミックスイン

多重継承は、小さな機能追加用クラスを組み合わせるためにも使われる。
このような小さな基底クラスは、ミックスインと呼ばれることがある。

問題点

同名メンバの曖昧さ

複数の基底クラスが同じ名前のメンバ関数を持つと、どれを呼ぶべきか曖昧になることがある。

class USBDevice
{
public:
    long getID() const
    {
        return 0;
    }
};
 
class NetworkDevice
{
public:
    long getID() const
    {
        return 1;
    }
};
 
class WirelessAdapter : public USBDevice, public NetworkDevice
{
};

このとき、WirelessAdapterのオブジェクトに対してgetID()をそのまま呼ぶと、どちらのgetID()か決められずコンパイルエラーになる。

必要なら、USBDevice::getID()のようにスコープ解決演算子で明示する。

菱形継承問題

あるクラスを、共通の基底クラスを持つ2つのクラスからさらに多重継承すると、ダイヤモンド型の継承関係になることがある。

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

このような場合、CopierPoweredDeviceを1つ持つべきか2つ持つべきか、共通基底クラスのメンバ参照をどう扱うか、といった問題が生じる。

注意

  • 多重継承は便利なこともあるが、名前の衝突や保守性の低下を招きやすい
  • 特に菱形継承問題は複雑さの大きな原因になる
  • コンポジションや単一継承で、多重継承を使う理由を解決できる場合が多いので、そちらを優先すべき

参考