class System
{
public:
virtual ~System() final { Shutdown(); };
virtual void Shutdown() = 0;
}
class DerivedSystem : public System
{
public:
virtual void Shutdown() override;
private:
Object* MySelfAllocatedObj;
}
这是我的用例,
我有一个管理器,其中包含一个由其他各种“模块”注册的System *列表,这些System *中的每个实际上都是被删除的类,对于System Manager来说是未知的。
这些模块在各自的System *应该结束/死亡时将请求Shutdown()。
因此,如果其中一个DerivedSystem具有MySelfAllocatedObj(ptr)并将其作为Shutdown()的一部分销毁,那么可以使用当前体系结构正确清理我的内存吗?
我这样做是为了限制“销毁”功能的数量,例如Destructor / Shutdown,但不想将析构函数公开给“请求该DerivedSystem的模块”
其他:如果DerievedSystem类声明一个析构函数会发生什么?
编辑: 添加了:公共系统(继承)
问题不是我是否应该这样,问题是,我的内存是否将被正确清除,或者是否被管理器破坏了
delete System*
或通过请求模块(第三方)调用
SystemManager->RequestShutdown(SystemID...) { System->Shutdown()};
两条路径都会以相同的“内存清除”结束还是我会错过某些东西?
重点是这两个函数中没有重复的代码。
答案 0 :(得分:3)
在析构函数中,任何派生对象的生存期已经结束,就像在构造函数中一样,任何派生对象的生存期尚未开始。在析构函数(或构造函数)中对虚拟函数的调用将静态地调度,因为不再有派生对象可以派发到的派生对象(或在构造函数的情况下不存在派生对象)动态地。除非您定义System::Shutdown
,否则该程序不太可能成功链接。
此外,声明基数final
的析构函数将阻止您派生此类基数,因为即使隐式生成的派生类的析构函数也将是“替代”。
我的记忆是否可以正确清理,或者被Manager破坏
delete System*
您的伪代码不清楚,但是从描述中我了解到您删除了System*
类型的指针
否,因为从未调用过1. DerivedSystem::shutdown
,而且因为2. DerivedSystem
格式错误,因为它覆盖了最终的析构函数,并且程序不太可能编译。
SystemManager->RequestShutdown(SystemID...) { System->Shutdown()};
这将称为DerivedSystem::shutdown
,因此它应该在这方面起作用。但是,班级的畸形仍然是一个问题。
这些模块在各自的System *应该结束/死亡时将请求Shutdown()。
我这样做是为了限制“破坏”功能的数量,例如Destructor / Shutdown
如果您想限制销毁功能的数量,一个简单的解决方案是根本不提供Shutdown
功能,而是让系统在应死的情况下销毁其各自的系统。
如果确实需要单独的Shutdown
函数(我不建议这样做),并且想在析构函数中重用它,则需要在每个派生类的析构函数中调用它。
PS。显式删除和指向拥有资源的裸指针非常容易出错。最好改用智能指针。