2017-08-02 106 views
0

在這個關於Curiously Recurring Template Patten的網頁中,可以在堆棧上實例化派生類(Object Counter示例,其中基類模板具有受保護的析構函數):CRTP-wiki ..我編譯了自己。受保護的析構函數禁止在堆棧上創建派生類的對象?

template <typename T> 
struct counter 
{ 
    static int objects_created; 
    static int objects_alive; 

    counter() 
    { 
     ++objects_created; 
     ++objects_alive; 
    } 

    counter(const counter&) 
    { 
     ++objects_created; 
     ++objects_alive; 
    } 
protected: 
    ~counter() // objects should never be removed through pointers of this type 
    { 
     --objects_alive; 
    } 
}; 
template <typename T> int counter<T>::objects_created(0); 
template <typename T> int counter<T>::objects_alive(0); 

class X : counter<X> 
{ 
    // ... 
}; 

class Y : counter<Y> 
{ 
    // ... 
}; 

但這種回答說使基類的析構函數保護將禁止在堆棧上實例化派生類:answer

前面已經回答了,波科:: RefCountedObject保護了析構函數,因此所有的類繼承它不能在堆棧上創建....

所以,

(1)是這個答案錯了​​?還是我誤解了?

(2)爲什麼CRTP示例使析構函數受到保護?是否意味着禁止在堆棧上實例化基類模板的專門化?我可以在堆上實例化基類模板的專門化(我試過了,我不能,但不知道爲什麼)?

在此先感謝!

+2

請勿鏈接到代碼示例。鏈接死亡。把代碼放在問題中。特別是不要鏈接到包含大量不相關代碼示例的頁面。你真的期望每個人都*看*你想問什麼? – StoryTeller

+0

@StoryTeller感謝您指出這一點,我已經添加了代碼。但請下次再問:) – user8385554

+3

好吧,很簡單。由於寫作錯誤或缺乏知識,您鏈接的答案是錯誤的。受保護的析構函數不會阻止創建被欺騙的對象。 – StoryTeller

回答

1

我創建了一個示例,堆棧和堆上的對象都可以創建。 我認爲答案是錯誤的,並且保護析構函數具有在您的代碼片段中的註釋中給出的確切含義:「永遠不要通過此類指針刪除對象」。另外,如果析構函數是虛擬的,那麼'protected'可以被跳過(因爲delete將總是首先調用繼承的析構函數)。我希望我在這裏沒有錯過任何東西。

#include <cstdio> 

template <typename T> 
struct counter 
{ 
    static int objects_created; 
    static int objects_alive; 

    counter() 
    { 
     ++objects_created; 
     ++objects_alive; 
    } 

    counter(const counter&) 
    { 
     ++objects_created; 
     ++objects_alive; 
    } 
protected: 
    ~counter() // objects should never be removed through pointers of this type 
    { 
     --objects_alive; 
    } 
}; 
template <typename T> int counter<T>::objects_created(0); 
template <typename T> int counter<T>::objects_alive(0); 

class X : counter<X> 
{ 
public: 
    X() 
    { 
     printf("Hello from X %dth instance, %d still up\n", objects_created, objects_alive); 
    } 

    ~X() 
    { 
     printf("Bye X\n"); 
    } 
}; 

int main() 
{ 
    { 
     X x; // hello x1 
     { 
      X x2; // hello x2 
     } // bye x2 

     X* x3 = new X(); // hello x3 
     X* x4 = new X(); // hello x4 

     delete x3; // bye x3 

     counter<X>* x5 = (counter<X>*)x4; 

     delete x5; // destructor is inaccesible, does not compile 
    } 
    return 0; 
} 
相關問題