6

簡単に言えば、C++ で単一レベルの継承用のインターフェイスを作成するにはどうすればよいでしょうか (単純さと教訓的な理由から)。ポリモーフィズムを使用していないが、基本クラスに仮想抽象メソッド ( ) が含まれているコードを見ましたvirtual void TheMethod() = 0

純粋仮想メソッドを使用してこの抽象クラスからクラスが派生しましたが、後続のコードでは、派生クラスのインスタンスが動的割り当てをまったく使用せずに使用されました。

これは正しい方法ですか?ポリモーフィック デザインの使用によって推測されるオーバーヘッドについてはどうでしょうか。

これは問題外だと思います..これは、そのメソッドが純粋な仮想メソッドであっても、基本メソッドを非表示/ゴースト化するように見えます。

後で編集:いくつかの良い答えを提供してくれたすべての人々に感謝します。ポリモーフィズムと互換性のある唯一のものとして、このオブジェクト作成の可能性を強調する意味で、「動的割り当て」の使用から生じた重大なエラーに下線を引きたいと思います. この実行時の呼び出し動作を利用する唯一の方法 (しかし、おそらく最も一般的な方法) ではないことは明らかですが、私の元の質問をさらに明確にするために:

純粋仮想メソッドを使用せずにプログラマーにメソッドを実装させる方法はありますか? 私のおそらく不当な懸念は、ポリモーフィック デザインへの扉を開いたことが、パフォーマンス面でも少し重いかどうかということです (議論中のメソッドに対して 1 秒あたり数千回のそのような呼び出しについて話します)。

後で編集:ベースに保護されたコンストラクターを持たせることは、直接インスタンス化できないことを意味し(ファクトリーまたは他の友好的な手段を使用することを除いて)、これにより、純粋な仮想メソッドが誘発する効果の1つを補うことができます。しかし、派生クラスが独自のメソッド実装を提供していることを確認するにはどうすればよいでしょうか? 関連付けられた vtable を持つという誇張された懸念が実際にはそれほど大したことではない場合は、純粋な仮想メソッドを使用することに固執します (SFINAE の奇妙な繰り返しのテンプレート パターンは、そうでない人にとっては読みにくく、理解するのが難しいためです)。中級以上の C++ プログラマー - 私のように :) )。

4

4 に答える 4

5

ポリモーフィックに使用するためにオブジェクトを動的に割り当てる必要はありません。

struct base {
    virtual void foo() = 0;
};

struct derived : base {
    virtual void foo() {
        // do stuff
    }
};

void f(base& object) {
    object.foo();
}

int main() {
    derived object; // no dynamic allocation at all
    f(object); // polymorphism happens here
}
于 2012-08-24T08:26:23.737 に答える
5

教訓的な理由から、目的が C++ でポリモーフィック オブジェクトを実装する方法を理解し、作成した型をテストすることである場合、動的割り当ては必要ありません。ただし、実際のアプリケーションでは、多態性を使用する主な理由は実行時まで具体的な型がわからないため、おそらくそうなるでしょう。

C++ (およびそれをサポートする実質的に他のすべての言語) では、ポリモーフィズムには、C++ がデフォルトで使用する値セマンティクスではなく、参照セマンティクスが必要であることに注意してください。通常、基本クラスとして使用するように設計されたクラスは、コピーと代入をサポートしませんclone()(仮想関数を介したものを除く)。

オーバーヘッドに関して: 何と比べて? 通常、仮想関数の呼び出しは、非仮想関数の呼び出しよりもコストがかかります。ただし、仮想関数を使用している場合は、ランタイム ディスパッチが必要なためです。他のメカニズムを使用してこれをシミュレートすると、さらにコストがかかる可能性があります。

于 2012-08-24T08:43:33.043 に答える
3

はい、他の人が述べているように、基本的には純粋な仮想(抽象)メンバー関数を持ち、データメンバーを持たないクラスを使用します。このインターフェースを実装する場合、当然これらのメソッドを提供する必要があります。

一方、これは動的割り当てとは何の関係もありません。自動オブジェクト (つまり、スタック) または動的オブジェクト (つまり、ヒープ) のどちらを使用するかは、ポリモーフィを含むそれらの使用方法には関係ありません。動的バインディングのことですか?

以上のことから、テンプレートでの動的バインディング (つまり「ポリモーフィズム」) を使用せずにインターフェースを実装できます。基本的に、SFINAE+CRTP を使用して、テンプレート クラスからプライベートに継承することにより、特定のメンバー関数が存在するかどうかを確認します。基本的に、親クラス (仮想メンバーを含まない) template <typename T> class FooIface;( as から継承) は、それを呼び出そうとすることによってメンバー関数があるclass Foo : private FooIface<Foo>ことを確認します。メタプログラミングのトリックを使用して、型が正しいことを確認することもできます。Tfoofoo

しかし、これはおそらく面倒すぎて読みにくいでしょう。抽象基本クラスは、一般的なアプローチです。

于 2012-08-24T08:35:15.813 に答える
1

C++ にはInterfaceの概念がなく、 Abstract クラスを使用してのみ動作をシミュレート
できます。 抽象クラスは、少なくとも 1 つの純粋仮想関数を持つクラスです。抽象クラスのインスタンスを作成することはできませんが、それへのポインターと参照を作成することはできます。また、抽象クラスから継承する各クラスは、インスタンスを作成できるように純粋仮想関数を実装する必要があります。

ダイナミック アロケーションポリモーフィズムは関係ありません。

動的割り当ては、オブジェクトが割り当てられる場所を定義、自動変数に提供される暗黙的なメモリ管理とは異なり、オブジェクトが明示的なメモリ管理を持つ必要があることを定義します。

ポリモーフィズムとは、1 つのものの複数の形態を意味。これは、クラスで異なる動作を持つ同じ関数です。スタック上のオブジェクトを指す基本クラスのポインターを持ち、ポリモーフィックな動作を維持できます。

于 2012-08-24T08:25:54.703 に答える