19

次のコードがあるとします。

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

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

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

abstractFunction問題の行を追加しないと、 で宣言されていないというコンパイル エラーが発生しますDerived。私は VS 2008 を使用しています。
なぜこの特定の行が必要なのかわかりません (これをクラス宣言の外で提供される関数定義と混同しないでください)。. それはビジュアルスタジオの問題ですか、それともC++標準によって強制されていますか?IinterfaceabstractFunction

4

4 に答える 4

8

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

さらに、それは意味がありません。派生クラスが抽象かどうかの問題は、コンパイル時にどこでもわかっている必要があります。オーバーライドの実装は、通常、1 つの変換単位でのみ提供されるため、実際に関数をオーバーライドすることを意味しているという事実をプログラムの残りの部分に伝えることは不可能です。

于 2012-11-19T07:22:25.123 に答える
2
  1. はい:オブジェクトを作成する場合class Derived
  2. いいえ:抽象class Derivedも保持したい場合
  3. いいえ:関数をすでにオーバーライドしている中間クラスがある場合、
    たとえば、との間IinterfaceでオーバーライドしてDerivedいるaがある場合。そのため、同じものをオーバーライドすることはオプションですclass IntermediateabstractFunction()class Derived

編集:変更された質問のタイトルで、

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

これは、C ++コンパイラの文法では、(またはまたはファイル)のすべてのメンバー関数をclass(またはまたはファイル)本体namespace内で宣言する必要があるためです。それか正常な機能か。関数のためだけにその一貫性を破る正当な理由 はありませんclassnamespacevirtual
virtual

于 2012-11-19T07:10:23.003 に答える
1

an で終わる関数=0は a と呼ばれます。これは、特定のコンストラクター (コピー ctor が削除されているdeleted functionなど) を使用するオブジェクトが必要ない場合に役立ちます。unique_ptr

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

プロトタイプ/実装のアイデアがコードを記述する唯一の方法ではないことを覚えておいてください。実装をクラスに正しく配置することもできます (コードが十分に小さく、関数をインライン化したい場合に実行できます)。もう一度、削除された仮想機能を明示的にオーバーライドする必要があります。とにかくオーバーライドする必要があるため、プロトタイプで明示的にオーバーライドする必要があることは完全に理にかなっています。それ以外の場合、関数は引き続き削除されます。

具体的な例として、List.hpp、List.cpp、main.cpp があるとします。

List.hpp には、抽象クラスと、抽象クラスから継承する通常のクラスがあります。#include "List.hpp"List.cpp ではなく、主にあなたですよね?そのため、コンパイラはそのファイルの内容を (コンパイルを試みるまで) 認識しません。削除された仮想関数がオーバーライドされていない場合、コンパイラは単に抽象クラスをインスタンス化しようとしているだけであると判断し、エラーをスローします。

一方、List.cpp をコンパイルしている場合、コンパイラはエラーをスローします。今回は、記述しようとしている関数が実際には定義されていないことを訴えます。Base::deletedFunction()とは異なるからですDerived::deletedFunction()

于 2012-11-19T07:19:29.330 に答える
0

はい、純粋仮想関数の要点は、派生クラスでオーバーライドすることを強制することです。この宣言は C++ で明示的に行う必要があります

于 2012-11-19T07:07:12.100 に答える