次のようなものを使用することの長所と短所は何ですか
template <typename TData>
class Base {
public:
void foo()
{
static_cast<TData*>(this)->doFoo();
}
};
class Derived : public Base<Derived>
{
void doFoo() { \*...*\ }
};
の代わりに
class Base {
virtual ~Base = default;
virtual void foo() = 0;
};
class Derived {
void foo() final { \*...*\ }
};
?
私が理解している限り、どちらのアプローチも実行時にvtable-lookupを回避しますよね?では、どのような状況で、より多くの定型文を含む最初の方法を使用する必要がありますか?
CRTPを介した静的ポリモーフィズム(最初のケース)はコンパイル時に実行されます。コンパイル時にすべてのクラスがわかっている場合は、基本的にそれをお勧めします。注もいることBase
自体が、クラスが、クラステンプレートではありません、そうBase
でないの基底クラスDerived
。
パフォーマンスだけでなく、最初に使用するか2番目に使用するかをプロジェクトで決定することも重要です。
2番目のケースでBase
は、多形的な振る舞いのベースですDerived
。派生メソッドの呼び出しは、Baseへのポインタを介して呼び出すことができます。例:
Base* b = new Derived();
b->foo(); // calls Derived::foo via vtable lookup.
foo()の呼び出し方法に応じて、コンパイラーはそれを非仮想化するかどうかを指定できます。
Base* b = new Derived();
b->foo(); // cannot be devirtualized
Derived* d = new Derived();
d->foo(); // probably can be devirtualized, because compiler knows
// via final that none can override foo,
// so it doesnt need to consult vtable.
基本的に、パフォーマンスだけでなく堅牢性のために、コンパイル時に実行できるすべてのことを好みます。実行時エラーは処理が困難です。しかし、それは設計上の決定でもあります。最初の方法でプロジェクトがより複雑になり、パフォーマンスの低下が小さいことが問題にならない場合は、2番目のアプローチで非常にうまくいくことができます。
「万能」の解決策はありません。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加