web-dev-qa-db-ja.com

非仮想メソッドのオーバーライド

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++で奇妙なことが起こりました。

誰かが説明を手伝ってくれますか?

58
Leif Lazar

うん、あなたは少し誤解しています。

この場合、派生クラスの同じ名前のメソッドは親メソッドを非表示にします。そうでない場合は、基本クラスの非仮想メソッドと同じ名前のメソッドを作成しようとするとエラーがスローされるはずです。それは許可されており、問題ではありません-そして、あなたがやったように直接メソッドを呼び出すなら、それはうまく呼び出されます。

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

たとえば、次の行を追加してみてください。

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

...そして期待どおりに出力を観察します:

ベース:非仮想ディスプレイ。
ベース:仮想ディスプレイ。
ベース:非仮想ディスプレイ。
派生:仮想ディスプレイ。

85
sje397

はい、あなたは少し誤解しています:

純粋な仮想機能:

virtual void fun1()=0->は派生クラスでオーバーライドする必要があります

仮想機能:

virtual void fun2()->オーバーライドできます

通常の機能:

void fun3()->オーバーライドしない

ランタイムポリモーフィズムを実現するには、C++で仮想関数をオーバーライドする必要があります

5
Avinash Aitha

静的バインディングと動的バインディングのコンテキストでそれを見る方が良いかもしれないと思います。

メソッドが非仮想の場合(Javaとは異なり、C++ではデフォルトで既に存在します)、メソッドはコンパイル時に呼び出し元にバインドしますが、実行時にポイントされる実際のオブジェクトを知ることはできません。そのため、変数のタイプが重要であり、それが「ベース」です。

3
stdout