1. ホーム
  2. c++

[解決済み] 非仮想的なメソッドのオーバーライド

2023-01-04 18:48:19

質問

Visual C++ 2010でこのようなシナリオを想定してみましょう。

#include <iostream>
#include <conio.h>

using namespace std;

class Base
{
public:
    int b;
    void Display()
    {
        cout<<"Base: Non-virtual display."<<endl;
    };
    virtual void vDisplay()
    {
        cout<<"Base: Virtual display."<<endl;
    };
};

class Derived : public Base
{
public:
    int d;
    void Display()
    {
        cout<<"Derived: Non-virtual display."<<endl;
    };
    virtual void vDisplay()
    {
        cout<<"Derived: Virtual display."<<endl;
    };
};

int main()
{
    Base ba;
    Derived de;

    ba.Display();
    ba.vDisplay();
    de.Display();
    de.vDisplay();

    _getch();
    return 0;
};

理論的には、この小さなアプリケーションの出力は次のようになるはずです。

  • ベース。非仮想的なディスプレイ。
  • ベース。仮想ディスプレイ。
  • ベース。非仮想的なディスプレイ。
  • 派生。仮想ディスプレイです。

というのは、BaseクラスのDisplayメソッドは仮想メソッドではないので、Derivedクラスはこれをオーバーライドできないはずだからです。そうですよね?

問題は、アプリケーションを実行すると、このように出力されることです。

  • ベース。非仮想的なディスプレイです。
  • ベース。仮想ディスプレイ。
  • 派生。非仮想的な表示です。
  • 派生。仮想ディスプレイです。

つまり、私が仮想メソッドの概念を理解していなかったのか、それともVisual C++で何かおかしなことが起きているのか、どちらかです。

どなたか解説をお願いします。

どのように解決するのですか?

そうですね、少し誤解していますね。

派生クラス上の同名のメソッドは、この場合、親メソッドを隠します。もしそうでなければ、ベースクラスの非仮想メソッドと同じ名前のメソッドを作成しようとすると、エラーが発生するはずだと想像するでしょう。これは許可されており、問題ありません。そして、あなたが行ったようにメソッドを直接呼び出すと、それはうまく呼び出されます。

しかし、非仮想であるため、ポリモーフィズムを可能にする C++ のメソッド検索機構は使用されないでしょう。したがって、たとえば、派生クラスのインスタンスを作成し、ベース クラスへのポインタを介して 'Display' メソッドを呼び出した場合、ベースのメソッドが呼び出されますが、'vDisplay' では派生メソッドが呼び出されることになります。

例えば、以下の行を追加してみてください。

Base *b = &ba;
b->Display();
b->vDisplay();
b = &de;
b->Display();
b->vDisplay();

...そして、期待通りの出力を観察してください。

<ブロッククオート <ブロッククオート

ベースとなる 非仮想的な表示。

ベース。仮想ディスプレイ。

ベース。非仮想的なディスプレイ。

派生。仮想ディスプレイ。