28

C++ では、純粋仮想関数の実装を与えることは正当です。

class C
{
public:
  virtual int f() = 0;
};

int C::f() 
{
  return 0;
}

なぜあなたはこれをしたいのですか?

関連する質問: C++ faq liteには例が含まれています:

class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() = 0;
};

inline Funct::~Funct() { }  // defined even though it's pure virtual; it's faster this way; trust me

デストラクタが純粋仮想として宣言されてから実装される理由がわかりません。なぜこれが速くなるべきなのかというコメントがわかりません。

4

6 に答える 6

23

宣言されたデストラクタは、実装によって派生オブジェクトの破棄の一部として呼び出されるため、常に実装する必要があります。

他の純粋仮想関数は、有用な共通機能を提供するが、常に特殊化する必要がある場合に実装できます。この場合、通常、派生クラスの実装は、基本実装への明示的な呼び出しを行います。

void Derived::f()
{
    Base::f();

    // Other Derived specific functionality
}

通常、クラスを抽象化する必要がある (つまり、非派生インスタンスが作成されないようにする) 必要がある場合、デストラクタを仮想化しますが、そのクラスには本来純粋な仮想化である他の関数はありません。「信頼してください」は、派生オブジェクトのクリーンアップの一部として呼び出されるデストラクタが vtable ルックアップ メカニズムを使用する必要がないため、典型的な仮想関数呼び出しとは異なり、インライン実装を利用できるという事実を指していると思います.

于 2009-06-10T19:05:26.310 に答える
4

派生クラスが利用できるほど一般的な機能がある場合。しかし、彼らは他の仕事もする必要があります。

したがって、派生クラスは仮想関数を実装し、基礎となる基本バージョンを呼び出します。

class X: public C
{
    public:
        virtual int f()
        {
            return C::f() + 1; // I am +1 over my parent.
        }
};
于 2009-06-10T19:12:59.930 に答える
4

Herb Sutter がGuru of the Week #31でこの質問の最初の部分に答えていることがわかりました。

于 2009-06-10T20:15:19.150 に答える
2

こんばんは

基本クラスで宣言されたメンバー関数のデフォルトの実装を提供することに関して、現時点で私が考えることができる唯一の理由は、基本クラスを専門化している誰かのための可能な実装の選択肢として、動作のデフォルトの実装を提供したい場合です。 .

派生クラスの作成者は、独自の特殊な実装を追加する代わりに、基本クラスの作成者によって提供される既定の実装を使用することを選択できます。

これは一般的に、インターフェイスと動作のデフォルト実装を提供するための個別の関数を持つことに反対しているにもかかわらず、デフォルト実装と関連するインターフェイスを分離したいという人々のケースです。

ああ、例を提供する @Martin York の投稿を見たところです。

実際、Scott Meyers は彼の著書「Effective C++」でこれについて説明しています。初版の項目36です。

HTH

乾杯、

于 2009-06-10T19:23:39.067 に答える
0

仮想デストラクタの速度に関しては、これはデストラクタがヘッダーではなくcppファイルで定義されているためです。それは速度よりもサイズと関係があります。詳細については、「大規模C++ソフトウェア設計」で説明しています。残念ながら、すべての詳細を思い出せませんが、インライン仮想関数はvtableで複数回定義されていると思います。

ここでこれについての議論があります: インライン仮想関数は本当にナンセンスですか?

于 2009-06-11T10:40:35.290 に答える
0

次のように書くのは不適切であると見なされるためです。

class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() = 0 {};
};

このクラスから派生した場合、デストラクタは引き続き呼び出されます。すべてのメソッドを純粋仮想として宣言するのは、わかりやすくするためです。次のように書くこともできます。

class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() {};
};

少なくとも 1 つのメソッドが純粋仮想であるため、クラスは依然として抽象的です。デストラクタもまだインラインです。

于 2009-06-10T19:17:14.807 に答える