我写了以下愚蠢的政策结构:
template
<typename T>
struct SuperLeague
{
public:
void printLeague(){std::cout << "SuperLegue" << std::endl;};
protected:
//~SuperLeague(){}
};
和主持人类
template
<typename TT,template <typename C> class Policy>
class League: public Policy<TT>
{
public:
void fun()
{
Policy<TT>().printLeague();
}
};
我的主要是
int main()
{
League<int,SuperLeague> k;
League<int,SuperLeague> kk;
k.fun();
kk.printLeague();
League<int,SuperLeague> *kkk=new League<int,SuperLeague>();
kkk->fun();
//delete kkk;
};
直到这里,一切正常 . 输出是:
SuperLegue
SuperLegue
SuperLegue
在他的一本书中,Andrei Alexandrescu写道: Unless the policy class defines a virtual destructor, applying delete to a pointer to the policy class has undefined behavior . 他解释了在从策略类派生时不对策略或受保护(或私有)继承使用虚拟析构函数的原因,并建议 The lightweight, effective solution that policies should use is to define a nonvirtual protected destructor . 问题是当我尝试使用 ~SuperLeague(){}
时,编译器抱怨析构函数受到保护 . 我做错了什么?
2 回答
您不应该在
League::fun()
中创建临时策略对象 . 由于League
模板的实例派生自Policy
模板的相应实例,因此它继承了printLeague()
函数:当您声明析构函数
protected
时,您的解决方案无法编译的原因是protected
在访问对象时(或取消引用指向对象的引用或指针)时,可以从派生类访问基类成员 of the same derived class (在您的情况下为League
) .在您的示例中不是这种情况,您在该示例中创建
Policy<TT>
类型的临时对象并在该对象(不是League
类型)上调用printLeague()
.根据C 11标准第11.4 / 1段:
这将创建一个
Policy<TT>
类型的对象,在该对象上调用printLeague()
,然后销毁该对象 . 编译器抱怨破坏对象,因为析构函数受到保护 .由于
Policy<TT>
是基类,只需直接调用printLeague()
即可 .