class A {
public:
~A() { release(); }
virtual release() { cout << "~A"; }
}
class B : public A {
release() { cout << "~B"; }
}
当我删除B时,只调用一个类release()方法。
我想要实现的是每个子对象,当它被删除时,我想调用在每个子类中重写的释放方法,而不需要为每个调用release的子项手动指定析构函数(我是懒惰的) 。这实际上不可能以这种方式或任何其他方式实现吗?
答案 0 :(得分:6)
析构函数以构造函数的相反顺序执行,因此当A
中的B
被销毁时,其B
组件已被销毁,不再存在。在已销毁的对象上调用方法会产生未定义的行为,这就是为什么对虚方法的调用始终解析为<em>构造函数中的当前类类型或析
所以基本上没有,你不能这样做。你必须全部写下来。
答案 1 :(得分:3)
不要从析构函数或构造函数中调用虚方法 - 它们不会按照您的期望来执行。
退出懒惰并编写析构函数。
答案 2 :(得分:3)
此类问题的解决方案是预破坏阶段,您可以手动控制破坏的发生方式。
使用pImpl
模式实现您的对象。当包装对象被销毁时,通知pImpl
它将在销毁之前被销毁。
pImpl
可以有一个基类virtual PreDestroyable
类,允许子方法注册PreDestruction
回调,您可以在此预破坏阶段调用该回调。
class Destroyable {
protected:
Destroyable() {}; // must be empty
virtual ~Destroyable() { Assert(PreDestroyers.empty()); };
void RegisterPreDestroy( std::function<void()> const& func ) { PreDestroyers.push_back(func) );
private:
std::vector<std::function<void()>> PreDestroyers;
public:
// reverse order, reentrant:
void PrepareToDie() {
while (!PreDestroyers.empty()) {
auto f = PreDestroyers.back();
PreDestroyers.pop_back();
f();
}
}
};
// handles registration:
template<typename T>
class HasPreDestroyCode: public virtual Destroyable {
// TODO: usual CRTP static or dynamic checks:
T* self() { return static_cast<T*>(this); }
T const* self() const { return static_cast<T*>(this); }
HasPreDestroyCode() {
RegisterPreDestroy( [&]() { self()->PreDestroy(); } );
}
HasPreDestroyCode( HasPreDestroyCode const& other ) {
RegisterPreDestroy( [&]() { self()->PreDestroy(); } );
}
HasPreDestroyCode( HasPreDestroyCode const& other ) {
RegisterPreDestroy( [&]() { self()->PreDestroy(); } );
}
private:
HasPreDestroyCode& operator=( HasPreDestroyCode const& other ) = delete;
};
class Test: HasPreDestroyCode<Test> {
public:
void PreDestroy() {}
};
我上次在C ++ 11之前写过这些东西,所以我还没有弄清楚如何处理构造它的移动。它全部在运行时完成,而可能可以使用较少的运行时数据执行上述操作。类似于层次结构中包含预破坏代码的类型列表?