C ++:CRTP析构函数?

时间:2012-05-25 13:07:31

标签: c++ inheritance crtp

在项目中,我遇到以下问题:

我有一个非常简单的继承方案(我需要继承而不是组合):

class Base

- > class DerivedA

- > DerivedB类

- > class DerivedC

A,B和C派生自Base,这就是全部。 所以现在我有两个选择:

虚拟公共继承

没有虚拟的私有继承

出于某些优化原因(我需要很多内联)我不想要虚拟......我不想要私有继承。我认为唯一的选择是CRTP。但是基类有300个功能,在其中实现CRTP将是一个真正的痛苦。

所以我想知道以下解决方案是否有效:我只在基类的析构函数中使用CRTP:

template<class TCRTP> class Base
{
    ~Base() {delete static_cast<TCRTP*>(this);}
}

其中TCRTP将是DerivedA,B或C,我做公共继承。 它完全没问题,还是有问题?

非常感谢。

2 个答案:

答案 0 :(得分:8)

你的析构函数肯定是错误的。类的析构函数不会且不能delete对象的内存。

对没有虚函数的公共继承有什么异议? (至少)有两种方法可以防止某人通过基指针意外删除派生对象。一种是制作基础析构函数protected

另一种方法是将派生类的动态分配实例直接填充到shared_ptr。这甚至可以是shared_ptr<Base>

std::shared_ptr<Base> foo(new DerivedA(...));

由于shared_ptr具有捕获其参数类型的模板构造函数,因此Base*指针将在与DerivedA*关联的删除函数中转换为shared_ptr,因此删除正确。没有人会如此愚蠢地尝试从shared_ptr中提取指针并将其删除为Base*

当然,如果你没有虚函数,那么当衍生类之间的唯一区别就是它们在构造函数中设置的时候,这个技巧才真正有用。否则,您最终需要从Base*向下转换shared_ptr指针,在这种情况下,您应该首先使用shared_ptr<DerivedA>

答案 1 :(得分:1)

我可以看到在IUnknown::Release的实现中使用代码,但从不在析构函数中使用。 Base析构函数仅在派生对象被销毁后运行,尝试delete此时派生对象是未定义的行为。我很确定你会在那种特殊情况下获得无限递归。