仮想関数を使った継承
継承、仮想関数
本記事の前提条件は以下の通りです。
- 初心者向け
- とは言っても、何らかのプログラムはそれなりに書けるけど、C とか C++ はちょっと、という人向け
- ざっくり概要しか説明しないので細かいことは気にしないでいただきたい
- Visual Studio 2013 くらい~
- Windowsプログラム (CUI, GUI)
- コードの検証
- 開発環境: Visual Studio 2022, x64, Release ビルド
- 実行環境: Windows 10
- 本記事は上から順番に読む前提となっている
- 「Visual Studio 2013 くらい~」と書いてあるが、本記事の内容だと現在過去未来のどのバージョンでもほぼ同じ
- 「Windowsプログラム (CUI, GUI)」と書いてあるが、本記事の内容だとどの OS でもほぼ同じ
前提知識として必要と思われる情報
通常の継承と仮想関数の継承の違い
通常の継承
基底クラス
class Cook
{
public:
void Wash()
{
std::cout << "水道水で流し洗い\n";
}
void Cut()
{
std::cout << "包丁で切る\n";
}
void Grill()
{
std::cout << "コンロで焼く\n";
}
};
派生クラス
class Factory : public Cook
{
public:
void Wash()
{
std::cout << "超高圧洗浄\n";
}
void Cut()
{
std::cout << "レーザーで切る\n";
}
void Grill()
{
std::cout << "1万℃で焼く\n";
}
これを使ってみる。
Factory factory;
factory.Wash();
// -> 超高圧洗浄
基底クラスにキャストして使うと...。
Factory factory;
Cook& cook = static_cast<Cook&>(factory);
cook.Wash();
// -> 水道水で流し洗い
あくまでも基底クラスの処理が呼ばれる。
仮想関数で継承する
基底クラス
class Cook
{
public:
virtual void Wash()
{
std::cout << "水道水で流し洗い\n";
}
virtual void Cut()
{
std::cout << "包丁で切る\n";
}
virtual void Grill()
{
std::cout << "コンロで焼く\n";
}
};
派生クラス
class Factory : public Cook
{
public:
virtual void Wash() override
{
std::cout << "超高圧洗浄\n";
}
virtual void Cut() override
{
std::cout << "レーザーで切る\n";
}
virtual void Grill() override
{
std::cout << "1万℃で焼く\n";
}
同じように使ってみる。
Factory factory;
factory.Wash();
// -> 超高圧洗浄
基底クラスにキャストして使うと、
Factory factory;
Cook& cook = static_cast<Cook&>(factory);
cook.Wash();
// -> 超高圧洗浄
オブジェクトの実体であるクラスの処理が呼ばれる。
なお、この場合でも明示的に基底クラスの関数を呼ぶと、
Factory factory;
Cook& cook = static_cast<Cook&>(factory);
cook.Cook::Wash();
// -> 水道水で流し洗い
基底クラスの処理が呼ばれる。
以上。