带unique_ptr的受保护析构函数
protected destructor with unique_ptr
我正在尝试从第三方库调用API。
当我想将unique_ptr与具有受保护析构函数的类一起使用时,会出现麻烦。
这是一个例子,
#include <memory>
#include <iostream>
using namespace std;
class Parent {
public:
Parent () //Constructor
{
cout << "n Parent constructor calledn" << endl;
}
protected:
~ Parent() //Dtor
{
cout << "n Parent destructor calledn" << endl;
}
};
class Child : public Parent
{
public:
Child () //Ctor
{
cout << "nChild constructor calledn" << endl;
}
~Child() //dtor
{
cout << "nChild destructor calledn" << endl;
}
};
Parent* get() {
return new Child();
}
int main(int argc, char const* argv[])
{
Parent * p1 = get(); // this is ok
std::unique_ptr<Parent> p2(get()); // this is not ok
return 0;
}
我正在尝试将unique_ptr与父类一起使用。但是编译器抛出了错误
/usr/include/c++/5/bits/unique_ptr.h: In instantiation
of ‘void std::default_delete<_Tp>::operator()(_Tp*) const
[with _Tp = Parent]’:
/usr/include/c++/5/bits/unique_ptr.h:236:17: required
from ‘std::unique_ptr<_Tp, _Dp>::~unique_ptr() [with _Tp
= Parent; _Dp = std::default_delete<Parent>]’
main.cpp:38:35: required from here
main.cpp:12:5: error: ‘Parent::~Parent()’ is protected
~ Parent() //Dtor
^
In file included from /usr/include/c++/5/memory:81:0,
from main.cpp:2:
/usr/include/c++/5/bits/unique_ptr.h:76:2: error: within
this context
delete __ptr;
关于摆脱这个问题的任何想法?我无法破解父类和子类,因为它们是第三方库的类。
你可以让std::default_delete<Parent>
成为Parent
的朋友来修复这个错误。您可能还希望~Parent
virtual
避免在通过指针delete
派生类时出现未定义Parent
行为。
例如:
class Parent {
friend std::default_delete<Parent>;
// ...
protected:
virtual ~Parent();
// ...
但是,Parent
设计清楚地表明您不应该通过指针delete
Parent
这就是析构函数是非公共的原因。阅读虚拟了解更多详情:
准则 #4:基类析构函数应该是公共的和虚拟的,或者受保护的和非虚拟的。
您可能希望引入另一个中间基类来解决此问题:
class Parent { // Comes from a 3rd-party library header.
protected:
~Parent();
};
struct MyParent : Parent { // The intermediate base class.
virtual ~MyParent();
};
class Derived : public MyParent {};
std::unique_ptr<MyParent> createDerived() {
return std::unique_ptr<MyParent>(new Derived);
}
int main() {
auto p = createDerived();
}
不幸的是,摆脱这个问题的真正方法是不要从Parent
派生类,并且不使用std::unique_ptr<Parent>
管理Parent
对象(或任何派生类)的生存期。
换句话说,你需要重新设计你的类。
我这样说的原因是
- 如果有人不厌其烦地为
Parent
提供受保护的非虚拟析构函数,则其意图很可能是避免使用实际指向派生类实例并使用运算符delete
释放的Parent *
。 库设计者(通常)不会在没有充分理由的情况下这样做。 - 您的代码可以强制按原样编译(例如,通过
std::default_delete<Parent>
成为Parent
的朋友)。 但是,unique_ptr
使用std::default_delete
来释放托管对象。 它使用运算符delete
。 如果unique_ptr<Parent>
管理的对象是派生自Parent
的类型,则会给出未定义的行为。
所以,简而言之,你正在围绕(谁设计)你的第三方库的意图工作,如果你强迫代码编译,你的奖励将是未定义的行为。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 拥有"受保护的非虚拟析构函数"与"受保护虚拟析构构函数"有什么好处
- 受保护的析构函数禁用在堆栈上创建派生类的对象?
- 如何将 std::unique_ptr<Parent> 与具有受保护虚拟析构函数的只读父类一起使用
- 带unique_ptr的受保护析构函数
- 具有受保护析构函数的类数组的动态分配
- 抽象基类中的析构函数保护不会在 C++ 中继承
- 删除具有受保护析构函数的对象
- Keil:虚拟或受保护的析构函数和堆
- 基类中受保护的非虚拟析构函数
- 从保护类析构函数引发异常会导致 std::终止
- 全局变量构造函数/析构函数是否需要线程保护
- 提升::p ython 受保护的析构函数问题
- 是否有使受保护的析构函数成为虚拟的用途
- 删除具有受保护析构函数的对象
- C++中受保护的策略类的析构函数
- 受保护析构函数对象在堆vs堆栈上的分配
- 受保护的抽象基类的构造函数和析构函数
- 如何在具有受保护析构函数和公共销毁方法的 3'd 派对类上使用shared_ptr
- 处理CRTP设计的受保护/私有构造函数/析构函数