2012-11-19 17 views
13

は、私は次のコードがあるとします。C++の派生クラスでオーバーライドされた関数を再宣言する必要があるのはなぜですか?

class Iinterface 
{ 
    virtual void abstractFunction()=0; 
}; 

class Derived : public Iinterface 
{ 
    void abstractFunction(); // Do I need this line? 
}; 

Derived::abstractFunction() 
{ 
    // implementation here 
} 

私は疑問に行を追加しない場合、私はabstractFunctionDerivedで宣言されていないというエラーをコンパイルし得ます。私はVS 2008を使用しています。
なぜこの特定の行が必要なのか分かりません(これはクラス宣言の外で提供されている関数定義と混同しないでください)Iinterfaceから継承している限り明らかに私はabstractFunctionを宣言している。 Visual Studioに問題があるのですか、それともC++標準によって強制されていますか?

答えて

8

純粋仮想基本関数の宣言がすべての派生クラスに暗示されていた場合、純粋仮想基本関数に関して抽象的なままである派生クラスを持つことはできません。代わりに、すべての派生クラスはリンカーエラーを生成します。それは非常に直観的で紛らわしく混乱し、言葉の表現力が低下します。

さらに、派生クラスが抽象クラスであるかどうかは、コンパイル時にどこでもとする必要があります。オーバーライドの実装は、通常、単一の翻訳単位でのみ提供されるため、関数のオーバーライドを実際には意味するという事実を他のプログラムに伝えることは不可能です。

+0

あなたはそれをはるかに良く集計しました:) –

+0

私は同意します、これはおそらくわかりやすい答え、+1よりも理解できるでしょう。 – OmnipotentEntity

+0

派生クラスが抽象クラスかどうかは、C++にはない明示的な "抽象"キーワードで知ることができます。 –

0

はい、純粋な仮想関数のポイントは、派生クラスでそれを上書きするように強制することです。この宣言は、C++

+0

私はそれを認識していますが、私はそれをオーバーライドしています。クラス宣言内で関数のプロトタイプを書き直す必要がある理由はわかりません。 VSがそれ自体を推論しないのはなぜですか? – atoMerz

+0

VSはあなたがそのmetodについて忘れてしまったと思っています:) – whd

+0

クラス定義はオブジェクト階層設計を駆動するので、上で説明したimmillindのように、オーバーライド宣言を含めるかどうかを選択することで、対応するメソッドコードが存在するかどうかをコンパイラに指示します。 –

2
  1. はいで明示的である必要があります:あなたはclass Derived
  2. のオブジェクトを作成する場合:あなたもclass Derived抽象
  3. を維持したい場合いいえ:すでにオーバーライドされている中間クラスがある場合
    IinterfaceDerivedの間には、abstractFunction()をオーバーライドしたclass Intermediateがあります。 class Derivedが同じ

編集を上書きするので、今ではオプションです:変更された質問のタイトルで、

は、なぜ私は C++で派生クラスでオーバーライドされた関数を再宣言する必要がありますか?

C++コンパイラの文法が class(または namespaceまたはファイル)のすべてのメンバ関数が class(または namespaceまたはファイル)内で宣言されなければならないことを要求しているためだ

体。それはvirtualまたは通常の機能です。
がありませんvirtualの機能のためだけに、その一貫性を破るのに正当な理由があります。

+1

私は、OPが純粋仮想ベース関数をオーバーライドする仕組みを認識していると思います。彼女は*宣言*が派生クラスでなぜ必要なのかを知りたがっています。 –

+0

@KerrekSBありがとう、それは私が正確に意味していたものです。 – atoMerz

+0

@KerrekSB、質問のタイトルは今編集されているようです。私は答えを修正します。 – iammilind

1

=0で終了する関数はdeleted functionと呼ばれます。これは、特定のコンストラクタを使用するオブジェクト(たとえば、コピー先が削除されたunique_ptr)を必要としない場合に便利です。

virtual関数が削除された場合、標準でクラスは抽象型になります。ほとんどの場合、クラスのプロトタイプとクラスの関数本体は別々のファイルにあるため、削除された仮想関数をオーバーライドしていることをプロトタイプで明示的に説明しない限り、削除された仮想関数をオーバーライドしません。コンパイラは、完全に別のファイルに実装を見た後で、関数をそこに置くことを意図していると単に推測するだけではありません。

プロトタイプ/実装のアイデアはコードを書く唯一の方法ではないことを覚えておいてください。クラス内に実装を置くこともできます(コードが十分小さく、関数をインライン化したい場合に実行できます)。 )また、削除する仮想関数を明示的にオーバーライドする必要があります。とにかくそれをオーバーライドする必要があるので、プロトタイプで明示的にオーバーライドする必要があります。それ以外の場合、関数は削除されます。具体的な例

:あなたはあなたが抽象クラスから継承する抽象クラスと通常のクラスを持っているList.hpp、List.cppとList.hppでmain.cppに

を持っているとしましょう。あなたのメインでは#include "List.hpp"で、List.cppではありません。したがって、コンパイラはそのファイルに何が入っているかをIDEAに知らせません(コンパイルを試みるまで)。削除された仮想関数をオーバーライドしないと、コンパイラは抽象クラスをインスタンス化してエラーをスローすると考えています。

一方、List.cppをコンパイルする場合、コンパイラはエラーをスローします。今回は、書き込みしようとしている関数が実際には定義されていないと不平を言っています。 Base::deletedFunction()Derived::deletedFunction()とは異なります。

+0

ありがとうございます。これはコンパイラの制限かC++の制限ですか? – atoMerz

+1

C++の制限です。私はそれを限界と呼ぶことをためらっていますが。それはあなたがそれについて明示しなければならないということだけです。長期的にはあなたを助けます。 – OmnipotentEntity

関連する問題