102

I have a base class with a virtual function and I want to override that function in a derived class. Is there some way to make the compiler check if the function I declared in the derived class actually overrides a function in the base class? I would like to add some macro or something that ensures that I didn't accidentally declare a new function, instead of overriding the old one.

Take this example:

class parent {
public:
  virtual void handle_event(int something) const {
    // boring default code
  }
};

class child : public parent {
public:
  virtual void handle_event(int something) {
    // new exciting code
  }
};

int main() {
  parent *p = new child();
  p->handle_event(1);
}

Here parent::handle_event() is called instead of child::handle_event(), because the child's method misses the const declaration and therefore declares a new method. This could also be a typo in the function name or some minor difference in the parameters types. It can also easily happen if the interface of the base class changes and somewhere some derived class wasn't updated to reflect the change.

Is there some way to avoid this problem, can I somehow tell the compiler or some other tool to check this for me? Any helpful compiler flags (preferably for g++)? How do you avoid these problems?

4

10 に答える 10

91

g++ 4.7 以降、新しい C++11overrideキーワードを認識します。

class child : public parent {
    public:
      // force handle_event to override a existing function in parent
      // error out if the function with the correct signature does not exist
      void handle_event(int something) override;
};
于 2012-07-23T09:37:00.913 に答える
20

C# のoverrideキーワードのようなものは、C++ の一部ではありません。

gcc では-Woverloaded-virtual、基本クラスの仮想関数を同じ名前の関数で非表示にしないように警告しますが、シグネチャが十分に異なるため、オーバーライドされません。ただし、関数名自体のスペルミスによる関数のオーバーライドの失敗を防ぐことはできません。

于 2009-01-30T23:31:01.793 に答える
18

私の知る限り、それを抽象化することはできませんか?

class parent {
public:
  virtual void handle_event(int something) const = 0 {
    // boring default code
  }
};

www.parashift.com で、実際に抽象メソッドを実装できることを読んだと思いました。これは個人的には理にかなっています。それが行う唯一のことは、サブクラスにそれを実装するよう強制することです。実装自体を許可されていないことについて誰も何も言いませんでした。

于 2009-01-30T23:32:24.443 に答える
11

MSVC では、CLRoverride用にコンパイルしていない場合でも、CLR キーワードを使用できます。

g++ では、すべての場合にそれを強制する直接的な方法はありません。を使用して署名の違いをキャッチする方法について、他の人が良い答えを出しています-Woverloaded-virtual__attribute__ ((override))将来のバージョンでは、誰かがC++0x 構文を使用して同様の構文または同等の構文を追加する可能性があります。

于 2009-01-31T00:26:23.633 に答える
5

関数を抽象化して、派生クラスがオーバーライドする以外に選択肢がないようにします。

@Ray あなたのコードは無効です。

class parent {
public:
  virtual void handle_event(int something) const = 0 {
    // boring default code
  }
};

抽象関数は、本文をインラインで定義できません。になるように変更する必要があります。

class parent {
public:
  virtual void handle_event(int something) const = 0;
};

void parent::handle_event( int something ) { /* do w/e you want here. */ }
于 2009-01-31T07:56:38.467 に答える
3

I would suggest a slight change in your logic. It may or may not work, depending on what you need to accomplish.

handle_event() can still do the "boring default code" but instead of being virtual, at the point where you want it to do the "new exciting code" have the base class call an abstract method (i.e. must-be-overridden) method that will be supplied by your descendant class.

EDIT: And if you later decide that some of your descendant classes do not need to provide "new exciting code" then you can change the abstract to virtual and supply an empty base class implementation of that "inserted" functionality.

于 2009-01-30T23:12:45.293 に答える
2

Your compiler may have a warning that it can generate if a base class function becomes hidden. If it does, enable it. That will catch const clashes and differences in parameter lists. Unfortunately this won't uncover a spelling error.

For example, this is warning C4263 in Microsoft Visual C++.

于 2009-01-30T23:17:45.753 に答える