13

C++ が仮想関数を介してランタイム ポリモーフィズムを実装し、仮想キーワードが継承されていることは理解していますが、派生クラスでの仮想キーワードの使用は見られません。

たとえば、以下のケースでは、派生クラスに virtual キーワードをドロップした場合でも、ptr->method() 呼び出しは派生::メソッドに移動します。では、この仮想キーワードは派生クラスで何をしているのでしょうか?

#include<iostream>

using namespace std;

class base
{
public:
    virtual void method()
    {
        std::cout << std::endl << "BASE" << std::endl;
    }
};

class derived: public base
{
public:
    virtual void method()
    {
        std::cout << std::endl << "DERIVED" << std::endl;
    }
};

int main()
{
    base* ptr = new derived();
    ptr->method();
    return 9;
}
4

5 に答える 5

22

派生クラスのメソッドが基本クラスの 1 つの仮想メソッドと名前とシグネチャで一致し、一致したメソッドが仮想である場合、派生クラスのメソッドも仮想になります。したがって、技術的には、派生クラスでそのようなメソッドを «virtual» としてマークする必要はありません。ただし、C++11 より前は、コードを読む人にとって大きなヒントになるという理由だけで、これは良い習慣でした (基底クラスのすべての仮想関数を覚えておくのは難しいかもしれません)。

C++11 以降では、派生クラスでこれを行うための 2 つの追加キーワードがあり、読みやすさとコードの堅牢性の両方に役立ちます。それらは «override» と «final» です。たとえば、派生クラスのメソッドに «override» を配置すると、基本クラスの対応するメソッドが実際に確実に仮想化されます。«final» キーワードは同じことを行い、メソッドがさらにオーバーライドされるのを防ぎます。

これについては、こちらのブログで、より現実的な理論的根拠とコード例を書いています。

それが役に立てば幸い。幸運を!

于 2013-08-07T13:15:57.737 に答える
8

virtual基本クラスの宣言でのみ必要です。派生クラスではオプションであり、おそらくそれらの場合のリマインダーとして機能します。

C++11 ではoverride、物事をさらに明示的にするために導入されています。これは、派生クラスのvirtualメソッドを基本クラスのメソッドのオーバーライドとして明示的にマークします。

于 2013-08-07T13:10:35.923 に答える
8

何もない。どの関数が仮想かどうかを思い出させるのに役立ちます。

于 2013-08-07T13:06:07.883 に答える
0

仮想関数を持つ基本クラスでクラスを駆動する場合、およびドライブ クラス コンパイラで仮想関数をオーバーライドする場合、規則に従って、仮想キーワードが関数と共に暗黙的に割り当てられるため、仮想キーワードはドライブ クラスではオプションです。したがって、virtual キーワードを明示的に割り当てる必要はありません。ただし、このキーワードは、複数レベルの継承中に必要です。

例:

コードにこのコードを追加します。

   class derived: public base {
    public:
        virtual void method() {    // In this line virtual keyword is optional.
              std::cout << std::endl << "DERIVED :: method function" << std::endl;
        }

        virtual void display() {
              std::cout << std::endl << "DERIVED :: display function" << std::endl;
        }
   };

   class deriveChild: public derived {
        public:
            void method() {
                 std::cout << std::endl << "DERIVECHILD :: method" << std::endl;
            }

        void display() {
                 std::cout << std::endl << "DERIVECHILD:: display" << std::endl;
            }
   };

main() で以下のコードを使用すると、異なる出力が得られます。

   base  *ptr = new deriveChild();
   ptr->method(); // will compile and execute
   ptr->display(); // will generate error because display() is not part of base class.

ここで、deliverChild クラスの display() を使用する場合は、このコードを使用します。

   derived *ptr = new deriveChild();
   ptr->method(); // Compile and Execute 
   ptr->display(); // Compile and Execute
于 2013-08-07T13:47:45.737 に答える
0

派生クラスの暗黙的な仮想メソッドは、派生クラスでは仮想であるため、明示的に仮想定義する必要はありません。宣言すると冗長な宣言になります。

ptr->method();

コンパイラが上記のステートメントに遭遇したとき

-> 上記のステートメントを解決しようとします。method() 関数は仮想であるため、コンパイラはその呼び出しの解決を実行時に延期します。

->実行時に派生クラスのオブジェクトを作成したため、コンパイラはこのメソッドが派生クラスであることを認識します。

この仮想キーワードは派生クラスで何をしていますか?

このシナリオを考えてみましょう。Derived2 という派生クラスがもう 1 つあり、派生フォームを継承しており、独自の仮想メソッドを持っています。

 class derived2: public derived
{
public:
    virtual void method()
    {
        std::cout << std::endl << "DERIVED2" << std::endl;
    }
};

以下のように main で method() を呼び出す場合

int main()
{
    base* ptr = new derived2();
    ptr->method();   //derived2 class method() will get called
    return 9;
}

派生 2 の method() がデフォルトで仮想でない場合、派生バージョンの method() を呼び出すことになり、ランタイム ポリモーフィズムの利点が失われます。

したがって、c++ の作成者は、仮想キーワードの継承を階層化することで、ここで素晴らしい仕事をしました。

于 2013-08-07T14:07:14.517 に答える