仅调用派生类的析构函数

时间:2013-04-08 15:50:01

标签: c++ inheritance casting type-conversion

看看C ++语言标准,有没有办法只调用派生类析构函数,而不调用基类的析构函数?

所以,对于班级

class Base { public: virtual ~Base() {} };
class Derived : public Base { public: ~Derived();};

是否可以编写像

这样的代码
Base *basePtr = new Derived();
//do something with basePtr

// Now somehow destroy Derived while keeping Base - call ~Derived() only, 
// line below however will call both ~Derived() and ~Base() - how it can be done?
dynamic_cast<Derived*>(basePtr)->~Derived(); 

因此,在执行上面的代码之后,basePtr将仅指向Base对象,就好像它是由

创建的一样。
Base *basePtr = new Base();

加上在调用new Derived()和销毁派生类之间操纵basePtr对Base对象造成的任何修改?

或者,这是禁止的吗?这是不可能的吗?

4 个答案:

答案 0 :(得分:2)

不,这是不可能的。该标准要求销毁Derived对象会破坏整个对象,包括Base子对象。根据C ++对对象生命周期的理解,任何其他东西都不会是破坏。

根据您想要实现的目标,考虑从派生的第一个

中复制Base
std::unique_ptr<Base> basePtr(new Derived());
//do something with basePtr

basePtr.swap(std::unique_ptr<Base> (new Base(*basePtr))); //splice the Base part out of the derived object

//basePtr now points to the spliced Base object.

另一种方法是在boost::optional(或只是一个pimpl)中保存派生的其他成员并重置它以获得仍然具有其Base类部分的“剥离”Derived对象。但这不会影响虚函数调度。

答案 1 :(得分:0)

以相反的构造顺序自动调用析构函数。我不相信有任何解决方法。

答案 2 :(得分:0)

除非您的派生类与您的基类无关,否则无法做到这一点。

以自动方式调用析构函数。明确调用析构函数可能会导致未定义的行为。

答案 3 :(得分:0)

在你提出这个问题时,不可能实现你所要求的。除非您有内存泄漏,否则显式调用析构函数不会导致未定义行为的唯一情况是该对象是由placement new创建的。即使这样,调用析构函数也会自动调用每个成员和基类的析构函数。

这是应该的。否则,编写正确的容器类或内存管理器将非常困难。

标准表示对象的生命周期一进入析构函数就会结束。它不会成为基类对象。它完全不再是一个对象。而且,如果不是这种情况,那么在这样的伎俩之后从多个基础派生的类的状态是什么?

最终,这种功能的“需求”是糟糕设计的标志。我猜你的用例更可能需要组合。看看你是不是用一个新类来解决它,它包含一个当前基类的实例和一个可选的,可替换的组件(一个智能指针)一些虚拟类,它作为接口和新的公共基础您当前的派生类。这样你就可以在不接触底座的情况下移除(并破坏)这些子对象。