ネタ元 → 親の子、子知らず(C++ virtual キーワード)
ダイヤモンド継承だと予想外の挙動を示す典型的な例。
#include <iostream>
#include <string>
// 抽象猫
class AbstractCat {
public:
virtual std::string sound() const { return "にゃー"; }
};
// 生猫
class Cat : virtual AbstractCat {
public:
// 基底クラスの鳴き声で鳴く
void MakeSound() const { std::cout << sound() << std::endl; }
};
// 機械猫
class RoboCat : virtual AbstractCat {
public:
// できそこないの機械猫はまだ巧く鳴けない
virtual std::string sound() const { return "#$&*|ふじこ"; }
};
// アンドロ猫(生猫と機械猫のあいのこ)
class AndroidCat : public Cat, public RoboCat {
public:
// 電源投入時、一度鳴く
void power_on() { MakeSound(); }
};
int main() {
AndroidCat kitty; // アンドロ猫起動!
kitty.power_on();
}
さて、アンドロ猫は電源投入時になんと鳴くでしょ?
AndroidCat::power_on() から Cat::MakeSound() が呼ばれます。
Cat::MakeSound() は基底クラス(AbstractCat)で定義された
virtual-funcition: sound() で鳴き声を手に入れ、鳴いてます。
ですから実行結果は...
#$&*|ふじこ
です。えー!?