受保护的析构函数禁止在堆栈上创建派生 class 的对象?
Protected destructor disables creating derived class's objects on stack?
在这个关于 Curiously Recurring Template Patten 的网页中,派生的 class 可以在堆栈上实例化(Object Counter 示例,其中基础 class 模板具有受保护的析构函数):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>
{
// ...
};
但是这个答案说保护基础 class 的析构函数将禁止在堆栈上实例化派生的 class::
As answered already, Poco::RefCountedObject has protected destructor, so all classes inheriting from it can not be created on the stack....
所以,
(1) 这个答案错了吗?还是我理解错了?
(2)为什么CRTP例子要保护析构函数?这是否意味着禁止在堆栈上实例化基础 class 模板的特化?我可以在堆上实例化基础 class 模板的特化吗(我试过了,我不能,但不知道为什么)?
提前致谢!
我已经创建了一个示例,可以创建堆栈和堆上的对象。
我认为答案是错误的,保护析构函数的含义在您的代码段的评论中给出:"objects should never be removed through pointers of this type"。此外,如果析构函数是虚拟的,则可以跳过 '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;
}
在这个关于 Curiously Recurring Template Patten 的网页中,派生的 class 可以在堆栈上实例化(Object Counter 示例,其中基础 class 模板具有受保护的析构函数):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>
{
// ...
};
但是这个答案说保护基础 class 的析构函数将禁止在堆栈上实例化派生的 class:
As answered already, Poco::RefCountedObject has protected destructor, so all classes inheriting from it can not be created on the stack....
所以,
(1) 这个答案错了吗?还是我理解错了?
(2)为什么CRTP例子要保护析构函数?这是否意味着禁止在堆栈上实例化基础 class 模板的特化?我可以在堆上实例化基础 class 模板的特化吗(我试过了,我不能,但不知道为什么)?
提前致谢!
我已经创建了一个示例,可以创建堆栈和堆上的对象。 我认为答案是错误的,保护析构函数的含义在您的代码段的评论中给出:"objects should never be removed through pointers of this type"。此外,如果析构函数是虚拟的,则可以跳过 '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;
}