2009-09-10 9 views
20

fooがクラスDで宣言され、バーチャルマークされていない場合、の動的タイプにかかわらず、fooの実装をDと呼びます。C++では、仮想関数をオーバーライドすると自動的に仮想関数ですか?

D& d = ...; 
d.foo(); 

ただし、次のプログラムではそうではありません。誰もこれを説明できますか?メソッドが仮想関数をオーバーライドすると自動的に仮想メソッドですか?

#include <iostream> 

using namespace std; 

class C { 
public: 
     virtual void foo() { cout << "C" << endl; } 
}; 

class D : public C { 
public: 
     void foo() { cout << "D" << endl; } 
}; 

class E : public D { 
public: 
     void foo() { cout << "E" << endl; } 
}; 

int main(int argc, char **argv) 
{ 
     E& e = *new E; 
     D& d = *static_cast<D*>(&e); 
     d.foo(); 
     return 0; 
} 

上記のプログラムの出力は次のようになります。

E 
+4

はstatic_castは不要である - 'D&D = * static_castを(&e);' D&D = E 'と等価である。 '起因&D *にE */Eから暗黙キャストします/ D&。 –

+0

C++ 11で関数宣言に "override"を追加すると、基本クラス関数をオーバーライドする意図が明確になります。また、宣言した関数のbaseがconstと異なる場合(コンパイラからエラーがトリガされます)例えば、std :: exceptionから派生し、what()non-const)を宣言した場合に驚いています。 – Ghita

答えて

22

標準10.3.2(class.virtual)は言う:

仮想メンバ関数VFは、クラスベースおよび派生クラス内で宣言された場合、ベース、メンバ関数VFから直接または間接的に誘導されますBase :: vfと同じ名前と同じパラメータリストが宣言されている場合、Derived :: vfも仮想である(宣言されているかどうかにかかわらず)。

[脚注:同じ名前の関数仮想関数としての別のパラメータリスト(節以上)は必ずしも仮想ではなく、オーバーライドしません。オーバーライド関数の宣言に仮想指定子を使用することは合法ですが、冗長です(空のセマンティクスを持ちます)。アクセス制御(節class.access)は、上書きの決定には考慮されません。 ---端foonote]

17

クイック答えはノーかもしれないが、正解ははい

C++は、関数の隠蔽について知っているので、上書きしないでバーチャルなキーワードマークのないバーチャルファンクション。

+11

@ Yossarianだから、派生クラスの仮想関数を仮想として宣言して、意図が明確になるようにするのがよい方法です。彼のEffective C++の本でこれについて議論します。 –

+0

私は、派生したメソッドのバーチャルマーキングが事実上最終的になるとは聞いたことがありません。これにより、第3レベル微分が非仮想上書きになります。しかし私は、Tadeuszの標準の抽出物が「間接的」という言葉のためにこの信念を間違っていると証明しているのではないでしょうか? –

+2

@ v.oddou人々が「どこかで聞いたこと」が通常間違っていることを「私はどこかで聞いた」。 ;-) 'virtual'とマークされた同じシグネチャを持つ関数があれば、同じシグネチャを持つ派生関数はオーバーライドされます。 「仮想」を含む宣言が関連しないかどうかの「ギャップ」は、キーワードが基本的な外観の後に空のセマンティクスを持つからです。 –

0

あなたはeのオブジェクトのコピーを作成せずにdに入れます。したがって、d.foo()は通常の多態的な振る舞いに従い、派生クラスメソッドを呼び出します。基本クラスで仮想として宣言されたメソッドは、派生クラスでも自動的に仮想になります。

-1

出力( "E")は、動作すると予想されるとおりに動作します。

理由: その参照のダイナミック(つまりランタイム)タイプはEです.Dに静的なアップキャストを行っていますが、それはコースの実際のタイプを変更しません。

これは、仮想メソッドと動的ディスパッチの背後にある非常に考え方です。インスタンス化しているタイプの動作(この場合はE)が表示されます。

関連する問題