[英]protected destructor with unique_ptr
I am trying to call APIs from a third party library.我正在尝试从第三方库调用 API。
There is a trouble when I want to use unique_ptr with a class having protected destructor.当我想将 unique_ptr 与具有受保护析构函数的 class 一起使用时会出现问题。
Here is the example,这是示例,
#include <memory>
#include <iostream>
using namespace std;
class Parent {
public:
Parent () //Constructor
{
cout << "\n Parent constructor called\n" << endl;
}
protected:
~ Parent() //Dtor
{
cout << "\n Parent destructor called\n" << endl;
}
};
class Child : public Parent
{
public:
Child () //Ctor
{
cout << "\nChild constructor called\n" << endl;
}
~Child() //dtor
{
cout << "\nChild destructor called\n" << 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;
}
I am trying to use unique_ptr with Parent class.我正在尝试将 unique_ptr 与父 class 一起使用。 But the compiler threw the errors
但是编译器抛出了错误
/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;
Any idea about getting rid of this issue?关于摆脱这个问题的任何想法? I can't hack Parent and Child class since they are the classes of the third party library.
我不能破解 Parent 和 Child class 因为它们是第三方库的类。
You can make std::default_delete<Parent>
a friend of Parent
to fix that error. 你可以
std::default_delete<Parent>
的朋友Parent
来修复错误。 And you may also like to make ~Parent
virtual
to avoid undefined behaviour when delete
ing a derived class through Parent
pointer. 而且,您也可能希望将
~Parent
virtual
以避免在通过Parent
指针delete
派生类时发生未定义的行为。
Eg: 例如:
class Parent {
friend class std::default_delete<Parent>;
// ...
protected:
virtual ~Parent();
// ...
However, Parent
design makes it clear that you are not supposed to delete
through Parent
pointer, this is why the destructor is non-public. 但是,
Parent
设计清楚表明您不应该通过Parent
指针delete
,这就是为什么析构函数是非公共的。 Read Virtuality for more details: 阅读虚拟性以了解更多详细信息:
Guideline #4: A base class destructor should be either public and virtual, or protected and nonvirtual.
准则4:基类的析构函数应该是公共的和虚拟的,或者是受保护的并且是非虚拟的。
You may like to introduce another intermediate base class to solve the issue: 您可能想引入另一个中间基类来解决此问题:
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();
}
Unfortunately, the real way to get rid of this issue is to not derive classes from Parent
, and to not manage the lifetime of Parent
objects (or any derived classes) using std::unique_ptr<Parent>
. 不幸的是,摆脱此问题的真正方法是不从
Parent
派生类,并且不使用std::unique_ptr<Parent>
来管理Parent
对象(或任何派生类)的生存期。
In other words, you need to redesign your classes. 换句话说,您需要重新设计您的类。
The reasons I say this are 我说这的原因是
Parent
a protected non-virtual destructor, the intent is most likely to avoid having a Parent *
which actually points at an instance of a derived class and is released using operator delete
. Parent
一个受保护的非虚拟析构函数,则该意图最有可能避免使用Parent *
,后者实际上指向派生类的实例,并使用运算符delete
释放。 A library designer will not (normally) do this without good reason. std::default_delete<Parent>
a friend of Parent
). std::default_delete<Parent>
的一个朋友Parent
)。 However, std::default_delete
is used by unique_ptr
to release the managed object. unique_ptr
使用std::default_delete
释放托管对象。 And it uses operator delete
. delete
。 That gives undefined behaviour if the object being managed by the unique_ptr<Parent>
is of a type derived from Parent
. unique_ptr<Parent>
管理的对象是从Parent
派生的类型,则将产生未定义的行为。 So, in short, you're working around the intent of (whoever designed) your third party library and, if you force the code to compile anyway, your reward will be undefined behaviour. 因此,简而言之,您正在努力(无论是由谁设计的)第三方库的意图,并且,如果您无论如何都迫使代码进行编译,则您的报酬将是不确定的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.