1

查看 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() 和销毁 Derived 类之间操作 basePtr 引起的对 Base 对象的任何修改?

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

4

4 回答 4

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)中并重置它以获得仍然具有其基类部分的“剥离”派生对象。然而,这不会影响虚函数调度。

于 2013-04-08T16:01:41.977 回答
0

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

于 2013-04-08T15:56:48.640 回答
0

除非您的派生类与您的基类无关,否则这是不可能的。

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

于 2013-04-08T15:59:31.450 回答
0

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

这是应该的。否则很难编写一个正确的容器类或内存管理器。

标准说对象的生命周期在它进入析构函数时就结束了。它不会成为基类对象。它不再是一个对象,完全。另外,如果不是这种情况,那么在这种技巧之后,从多个基派生的类的状态会是什么?

归根结底,对这种功能的“需求”是糟糕设计的标志。我猜你的用例更可能需要组合。看看你是否不能用一个新的类来解决它您当前的派生类。这样您就可以在不接触底座的情况下移除(和破坏)这些子对象。

于 2013-04-08T16:18:18.790 回答