web-dev-qa-db-ja.com

バーチャル?オーバーライド?または両方? C ++

最後の数週間で、何かが仮想とオーバーライドについて私の頭を悩ませています。仮想関数で継承を行う場合は、virtualを追加して適切な関数を検索するようコンパイラーに知らせる必要があることを学びました。その後、c ++ 11には新しいキーワード-オーバーライドがあることも学びました。今、私は少し混乱しています。 プログラムで仮想キーワードとオーバーライドキーワードの両方を使用する必要がありますか、それとも1つだけを使用する方が良いですか?

自分自身を説明する-私が意味するもののコード例:

class Base
{
public:
    virtual void print() const = 0;
    virtual void printthat() const = 0;
    virtual void printit() const = 0;
};

class inhert : public Base
{
public:
    // only virtual keyword for overriding.
    virtual void print() const {}

    // only override keyword for overriding.
    void printthat() const override {}

    // using both virtual and override keywords for overriding.
    virtual void printit() const override {}
};

最良の方法は何ですか?

66
Daniel

関数をオーバーライドする場合、技術的にvirtualまたはoverrideを記述する必要はありません。

元の基本クラス宣言には、仮想としてマークするためのキーワードvirtualが必要です。

派生クラスでは、基本クラス関数と同じ型を持っているため、関数は仮想です。

ただし、overrideは、意図したオーバーライドが技術的にオーバーライドではない場合にコンパイルエラーを生成することにより、バグを回避するのに役立ちます。例えば。関数の型が基本クラスの関数とまったく同じではないこと。または、基本クラスのメンテナンスがその関数のタイプを変更すること、例えばデフォルトの引数を追加します。

同様に、派生クラスのvirtualキーワードは、さらに派生したクラスで関数が仮想であることを保証することにより、このようなバグをより微妙にすることができます。

一般的なアドバイスは、

  • 基本クラス関数の宣言にはvirtualを使用します。
    これは技術的に必要です。

  • 派生クラスのオーバーライドにoverride(のみ)を使用します。
    これはメンテナンスに役立ちます。

例:

struct Base { virtual void foo() {} };
struct Derived: Base { void foo() override {} };

注:
¹C++は、共変の生のポインターと生の参照結果をサポートします。共分散では、オーバーライドのタイプはまったく同じではありません。互換性のあるタイプのみです。

108