2017-08-18 16 views
1

CRTP(Curtainly Recurring Template Pattern)を実装するときに、デストラクタを仮想化する必要がありますか?そうでない場合は、適切な非仮想実装は何ですか?CRTPでデストラクタをどのように実装しますか?

私はうまくいけば、物事を容易にするために例を提供します:

template<typename T> 
class Base 
{ 
public: 
    virtual ~Base() 
    { 
     // Should this be virtual? Non-virtual? 
     std::cout << "Base::~Base()\n"; 
    } 
}; 

class Derived : public Base<Derived> 
{ 
public: 
    ~Derived() override 
    { 
     std::cout << "Derived::~Derived()\n"; 
    } 
}; 

int main() 
{ 
    Base<Derived>* b = new Derived; 
    delete b; 
} 

結果:

Derived::~Derived() 
Base::~Base() 

Live Sample Here

EDIT:ように、ランタイムポリモーフィズムを使用する例を更新しました適切なクリーンアップには仮想デストラクタが必要です。

答えて

3

CRTPベースクラスは、この意味で他のどのベースクラスとも変わりません。仮想デストラクタが必要なのはdeleteの型のオブジェクトがBase<Derived>へのポインタを介してDerivedに行く場合だけです。それ以外の場合、仮想デストラクタは必要ありません。

Base<Derived>* b = new Derived; 
delete b; // Base<Derived>::~Base<Derived> must be virtual 
0

あなたは仮想デストラクタを必要とし、その後派生オブジェクトを指しています、基本クラスのポインタにdeleteをコールするつもりなら、それはそれで全部です。 CRTPまたはCRTPなし。

1

示した例では、仮想デストラクタは必要ありません。仮想デストラクタは、基本クラスへのポインタを使用して呼び出す必要がある場合にのみ必要です。オーバーライドされた関数はこの場合仮想でなければなりません。あなたのようなCRTPクラスの場合、Tの代わりにBase<T>を削除する必要はほとんどありません。

int main() 
{ 
    Derived *a = new Derived(); 
    // we have the right type anyway, so dont actually need a virtual anything (even normal virtual methods) 
    delete a; 

    Derived *a = new Dervied(); 
    Base<Derived> *b = a; 
    // We are now deleting via a parent class, so this needs a virtual destructor. 
    // This is pretty uncommon with a simple CRTP however. 
    delete b; 
} 
関連する問題