C++:CRTP 析构函数

C++ : CRTP destructor?

本文关键字:析构函数 CRTP C++      更新时间:2023-10-16

在一个项目中,我有以下问题:

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

类基础

->类派生A

->类 衍生分贝

->类派生C

A,B和C派生自Base,仅此而已。所以现在我有 2 个选择:

虚拟的公共继承

没有虚拟的私人继承

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

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

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

其中 TCRTP 将是派生 A、B 或 C,我做公共继承。是完全可以的,还是有问题的?

谢谢。

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

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

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

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

由于shared_ptr有一个捕获其参数类型的模板构造函数,因此Base*指针将在与shared_ptr关联的删除器函数中转换为DerivedA*,从而正确删除。没有人应该愚蠢到试图从shared_ptr中提取指针并将其删除为Base*

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

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