15

メソッドがクラス内で宣言されるvirtualと、派生クラスでのオーバーライドも自動的に考慮virtualされ、C ++言語ではvirtual、この場合、このキーワードがオプションになります。

class Base {
    virtual void f();
};
class Derived : public Base {
    void f(); // 'virtual' is optional but implied.
};

virtual私の質問は:オプションにする理由は何ですか?

コンパイラーにそのように言われる必要は絶対にないことは知っていますが、そのような制約がコンパイラーによって強制されれば、開発者は恩恵を受けると思います。

たとえば、他の人のコードを読んだときに、メソッドが仮想であるかどうか疑問に思うことがあり、それを決定するためにそのスーパークラスを追跡する必要があります。また、一部のコーディング標準(Googlevirtual )では、すべてのサブクラスにキーワードを配置する必要があります。

4

5 に答える 5

12

ええ、この場合、コンパイラーに仮想を強制させる方が本当に良いでしょう。これは、下位互換性のために維持されている設計上のエラーであることに同意します。

ただし、それなしでは不可能なトリックが1つあります。

class NonVirtualBase {
  void func() {};
};

class VirtualBase {
  virtual void func() = 0;
};

template<typename VirtualChoice>
class CompileTimeVirtualityChoice : public VirtualChoice {
  void func() {}
};

上記により、funcの仮想化が必要かどうかにかかわらず、コンパイル時の選択肢があります。

CompileTimeVirtualityChoice<VirtualBase> -- func is virtual
CompileTimeVirtualityChoice<NonVirtualBase> -- func is not virtual

...しかし同意しましたが、それは関数の仮想性を探すコストのわずかな利点であり、私自身、私は常に、該当する場合はどこでも仮想を入力しようとします。

于 2010-06-03T07:28:24.913 に答える
6

関連する注意として、C ++ 0xでは、新しい属性構文を介してオーバーライドを明示的に適用するオプションがあります。

struct Base {
  virtual void Virtual();
  void NonVirtual();
};

struct Derived [[base_check]] : Base {
  //void Virtual(); //Error; didn't specify that you were overriding
  void Virtual [[override]](); //Not an error
  //void NonVirtual [[override]](); //Error; not virtual in Base
  //virtual void SomeRandomFunction [[override]](); //Error, doesn't exist in Base
};

属性を使用して、メンバーを非表示にするタイミングを指定することもでき[[hiding]]ます。コードはやや冗長になりますが、コンパイル時に多くの厄介なバグをキャッチできます。たとえば、既存の関数をオーバーライドするvoid Vritual()代わりに、まったく新しい関数を導入することになります。void Virtual()

于 2010-06-03T08:12:04.470 に答える
3

デザインの弱点、私は同意します。また、2つの異なるものに異なる構文があれば、それは本当に素晴らしいことだと思います。

  1. 仮想関数を宣言します。つまり、派生クラスでオーバーライドされる可能性のある関数です。(これにより、実際にはvtableに新しい関数エントリが追加されます。)
  2. 派生クラスの仮想関数をオーバーライドします。

関数をオーバーライドするときの現在のC++ルールでは、物事を簡単にねじ込むことができます。関数名を間違って入力した場合(またはそのパラメーターリストを間違えた場合)、実際には(2)ではなく(1)を実行します。

そして、エラー/警告はありません。実行時に驚きを得るだけです。

于 2010-06-03T07:33:40.173 に答える
2

言語は「良い」スタイルを強制することができないので、C++は一般的に試みさえしません。少なくともIMOは、このような冗長な指定子を含めることがどのような場合でも良いスタイルであるかどうかを疑問視する可能性があります(個人的には、それらが存在するのは嫌いです)。

(少なくとも一部)Googleのコーディング標準は、状況によっては意味があるかもしれませんが、C ++全般に関しては、一般的に、せいぜい平凡なアドバイスと見なされています。ある程度、彼らはそれを認めさえします-彼らが公然と述べているそれらのいくつかは、彼らの古いコードに合うために本当にそこにあるだけです。彼らが直接認めていない他の部分、そして(完全に正直に言うと)その議論はとにかく彼らの基準のいくつかをサポートしないでしょう(すなわち、それのいくつかは本当の正当性を欠いているようです)。

于 2010-06-03T07:28:09.303 に答える
0

これは良い質問です。基本クラスで仮想として宣言されている場合は、派生クラスで仮想メソッドを再宣言するのが良いスタイルであることに確かに同意します。言語にスタイルを組み込む言語がいくつかありますが(たとえば、Google Goや、ある程度はPython)、C++はそれらの言語の1つではありません。コンパイラは、派生クラスが基本クラスで「仮想」と宣言されたものにキーワード「仮想」を再利用しないことを検出することは確かに可能ですが(または、さらに重要なことに、派生クラスはと同じ名前の関数を宣言します)基本クラスであり、基本クラスで仮想として宣言されていません)、実際、多くのコンパイラには、これが発生した場合に警告(さらにはエラーメッセージ)を発行する設定があります。ただし、この段階では、それほど厳密ではないコードが多すぎるため、このような要件を言語で設定することは実用的ではありません。さらに、開発者は常に言語よりも厳格にすることを選択でき、コンパイラの警告レベルを上げることができます。

于 2010-06-03T07:37:24.297 に答える