Gaz*_*zoo 2 c++ inheritance destructor unique-ptr c++11
我有点困惑.基本上,我有两个不同的资源管理器(AudioLibrary和VideoLibrary),它们都从共享的BaseLibrary类继承.此基类包含对音频和视频的引用.音频和视频都从名为Media的父类继承.
我将数据保存在地图中,填充了unique_ptr.但令我惊讶的是,我发现当这些指针最终通过.erase被删除时,只调用了Media的基本析构函数.
我想我错过了一些东西,但我认为编译器/运行时库会知道它指向视频或音频并将其称为析构函数.
似乎并非如此.我被迫做这样的事情来实际收回我的所有资源:
void AudioLibrary::deleteStream( const std::string &pathFile )
{
auto baseStream = mStreams[ pathFile ].release();
mStreams.erase( pathFile );
// Re-cast!
auto aStream = static_cast<AudioStream*>( baseStream );
delete aStream;
}
Run Code Online (Sandbox Code Playgroud)
这是正常的行为吗?
更新:
你没事 - 当然这是析构函数缺失的'虚拟'.我想我最近只是想到虚拟和继承意味着什么越来越少,并且让我的头脑失去了它的功能,而不是概念本身.偶尔会发生在我身上.
默认删除器unique_ptr<T>是适当命名的default_delete<T>.这是一个无状态的函子,可以调用delete它的T *参数.
如果希望在销毁unique_ptr基类时调用正确的析构函数,则必须使用虚拟析构函数,或者在删除器中捕获派生类型.
您可以使用函数指针删除器和无捕获的lambda轻松完成此操作:
std::unique_ptr<B, void (*)(B *)> pb
= std::unique_ptr<D, void (*)(B *)>(new D,
[](B *p){ delete static_cast<D *>(p); });
Run Code Online (Sandbox Code Playgroud)
当然,这意味着您需要将删除器的模板参数添加到所有用途unique_ptr.将其封装在另一个类中可能更优雅.
另一种方法是使用shared_ptr,因为它会捕获派生类型,只要您shared_ptr使用std::shared_ptr<D>(...)或最好创建派生类型std::make_shared<D>(...).