2017-08-02 46 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; 
} 
相关问题