C++ 在C++; A类{ 公众: ~A(){release();} 虚拟发布(){cout
析构函数是以构造函数的相反顺序执行的,因此当AC++ 在C++; A类{ 公众: ~A(){release();} 虚拟发布(){cout,c++,C++,析构函数是以构造函数的相反顺序执行的,因此当AB中的A被销毁时,其B组件已经被销毁并且不再存在。对已销毁对象调用方法会产生未定义的行为,这就是为什么对虚拟方法的调用总是解析为当前cl构造函数或析构函数中的ass类型 所以基本上不,你不能这样做。你必须把它们全部写出来。不要从析构函数或构造函数调用虚拟方法-它们不会做你期望它们做的事情 停止懒惰,编写析构函数。这种问题的解决方案是一个预销毁阶段,您可以手动控制销毁的发生方式 使用pImpl模式实现您的对象。当包装对象被销毁时,请在销毁之前通知pIm
B
中的A
被销毁时,其B
组件已经被销毁并且不再存在。对已销毁对象调用方法会产生未定义的行为,这就是为什么对虚拟方法的调用总是解析为当前cl构造函数或析构函数中的ass类型
所以基本上不,你不能这样做。你必须把它们全部写出来。不要从析构函数或构造函数调用虚拟方法-它们不会做你期望它们做的事情
停止懒惰,编写析构函数。这种问题的解决方案是一个预销毁阶段,您可以手动控制销毁的发生方式 使用
pImpl
模式实现您的对象。当包装对象被销毁时,请在销毁之前通知pImpl
pImpl
可以有一个基本的virtual PreDestroyable
类,该类允许子方法注册predestrouction
回调,您可以在预销毁阶段调用该回调
class A {
public:
~A() { release(); }
virtual release() { cout << "~A"; }
}
class B : public A {
release() { cout << "~B"; }
}
类可销毁{
受保护的:
Destroyable(){};//必须为空
virtual~Destroyable(){Assert(PreDestroyers.empty());};
void RegisterPreDestroy(std::function const&func){PreDestroyers.push_back(func));
私人:
std::病媒预雌雄体;
公众:
//反向顺序,可重入:
无效准备就绪(){
而(!PreDestroyers.empty()){
auto f=PreDestroyers.back();
PreDestroyers.pop_back();
f();
}
}
};
//处理注册:
模板
类HasPreDestroyCode:公共虚拟可销毁{
//TODO:常规CRTP静态或动态检查:
T*self(){return static_cast(this);}
T const*self()const{return static_cast(this);}
HasPreDestroyCode(){
RegisterRedestory([&](){self()->PreDestroy();});
}
HasPreDestroyCode(HasPreDestroyCode常量和其他){
RegisterRedestory([&](){self()->PreDestroy();});
}
HasPreDestroyCode(HasPreDestroyCode常量和其他){
RegisterRedestory([&](){self()->PreDestroy();});
}
私人:
HasPreDestroyCode和运算符=(HasPreDestroyCode常量和其他)=删除;
};
类测试:HasPreDestroyCode{
公众:
void PreDestroy(){}
};
我上一次写这篇文章是在C++11之前,所以我还没有弄清楚如何处理移动构造它。这一切都是在运行时完成的,而像上面这样用较少的运行时数据来完成可能是可行的。类似于层次结构中包含预销毁代码的类型列表之类的东西?您希望这两种类型都被调用吗ed?不,是唯一的子版本()方法。销毁应该从最派生的类型开始,并向后工作到基本版本。如果在基本版本中调用虚拟版本()方法,该方法位于派生类型中,其析构函数已被调用,因此没有可访问或处理的有效成员。您希望执行什么操作。即使它按您期望的方式工作(但实际情况并非如此)你不能做任何有用的事情,所以不要做它。问题变成了你真正想要达到的目标?你应该在析构函数中清理,为什么不去做呢?我不明白你为什么要重新发明C++对象系统。我自己没想过,谢谢,这完全有道理:)
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() {}
};