受保护的析构函数禁用在堆栈上创建派生类的对象?

Protected destructor disables creating derived class's objects on stack?

本文关键字:派生 创建 对象 堆栈 析构函数 受保护      更新时间:2023-10-16

在这个关于好奇重复出现的模板 Patten 的网页中,派生类可以在堆栈上实例化(对象计数器示例,其中基类模板具有受保护的析构函数(: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>
{
// ...
};

但是这个答案说,保护基类的析构函数将禁止在堆栈上实例化派生类:答案:

正如已经回答的那样,Poco::RefCountedObject 具有受保护的析构函数,因此无法在堆栈上创建从它继承的所有类。

所以

(1(这个答案错了吗?还是我误会了?

(2( 为什么 CRTP 示例使析构函数受到保护?它是否意味着禁止在堆栈上实例化基类模板的专用化?我可以在堆上实例化基类模板的专用化吗(我试过了,我不能,但不知道为什么(?

提前感谢!

我已经创建了一个示例,并且可以在堆栈和堆上创建对象。 我认为答案是错误的,保护析构函数在您的片段中的注释中给出了确切的含义:"永远不应该通过这种类型的指针删除对象"。此外,如果析构函数成为虚拟的,则可以跳过"受保护"(因为删除总是首先调用继承的析构函数(。我希望我在这里没有错过一些东西。

#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 upn", objects_created, objects_alive);
}
~X()
{
printf("Bye Xn");
}
};
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;
}