1

驚いたことに、以下が正当な C++ であることを知りました。

struct A {
  void foo(int) const = 0;  // pure virtual
  // ...
};
void A::foo(int) const { /* ... */ }

これの賢明な使用例は何ですか? つまり、いつA::foo呼び出され、なぜこれが正しい/最良の実装なのですか? C++03 と C++11 の間に違いはありますか?


さて、同じ意図を持つ以前の質問(私は見つけられませんでした)がありました。ただし、それはC++ 11より前でした。したがって、私の最後の質問は引き続き有効です。

4

3 に答える 3

4

これの賢明な使用例は何ですか?

関数に適切なデフォルト実装、または基本クラスに関連するものの部分的な実装があるが、それでも派生クラスにそれを強制的にオーバーライドさせたい場合は、それを配置するのに適した場所です。

また、コメントに記載されているように、純粋仮想関数を持たないクラスを強制的に抽象化することもできます。これを行うには、デストラクタを純粋仮想化します。ただし、純粋な仮想であるかどうかにかかわらず、デストラクタには本体が必要です。

いつA::foo呼ばれるの?

非仮想的にのみ呼び出すことができます。例えば:

struct B : A {
    void f(int i) const {
        A::foo(i);    // non-virtual call
        // Do the B-specific stuff
    }
};

なぜこれが正しい/最良の実装なのですか?

別の方法は、実装されていない純粋な仮想関数に加えて、部分/デフォルト実装の新しい名前を発明することです。

C++03 と C++11 の間に違いはありますか?

いいえ。

于 2013-08-27T13:38:13.503 に答える
3

正規のユースケースは、実装が必要な純粋仮想デストラクタを提供することにより、クラスを抽象としてマークすることです。

C++98以前からのルールです。

于 2013-08-27T13:33:33.627 に答える
1

もちろん合法です。 純粋仮想関数とは、それが宣言されたクラスのインスタンスをインスタンス化できないことを意味し、実装できないことを意味します。
たとえば、C# のインターフェイスのようなものです。

それはどのような機会を提供しますか?
1. クライアントはデフォルトの実装を使用できます。
2.純粋な仮想デストラクタを持つクラスでリンカ エラーが発生しなくなりまし た (基本クラスへのポインタに削除を適用すると、派生クラスのデストラクタが呼び出され、その後で基本クラスのデストラクタが呼び出されます。実装を省略すると、リンカでエラーが発生します) )。

参考文献:純粋仮想メソッドでの実装の必要性については、Scott Myers 著の「Effective C++」という本で詳しく説明されています。

于 2013-08-27T13:48:15.583 に答える