我正在尝试从第三方库中调用API。
当我要对具有受保护的析构函数的类使用unique_ptr时遇到麻烦。
这里是例子,
#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;
}
我正在尝试将Parent_ptr与Parent类一起使用。但是编译器抛出了错误
/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;
关于摆脱这个问题的任何想法吗?由于它们是第三方库的类,因此我无法破解Parent and Child类。
答案 0 :(得分:3)
您可以使std::default_delete<Parent>
成为Parent
的朋友,以解决该错误。而且,当通过~Parent
指针virtual
派生类时,您可能还想制作delete
Parent
以避免未定义的行为。
例如:
class Parent {
friend class std::default_delete<Parent>;
// ...
protected:
virtual ~Parent();
// ...
但是,Parent
设计清楚地表明,您不应该通过delete
指针来访问Parent
,这就是析构函数是非公开的原因。阅读Virtuality了解更多详细信息:
准则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();
}
答案 1 :(得分:0)
不幸的是,摆脱此问题的真正方法是不从Parent
派生类,并且不使用{{1}管理Parent
对象(或任何派生类)的生存期}。
换句话说,您需要重新设计课程。
我说这的原因是
std::unique_ptr<Parent>
一个受保护的非虚拟析构函数,则该意图最有可能避免让一个Parent
实际指向派生类的实例,并且使用运算符Parent *
发布。没有充分的理由,图书馆设计人员就不会(通常)这样做。delete
设为std::default_delete<Parent>
的朋友)。但是,Parent
使用std::default_delete
来释放托管对象。并且它使用运算符unique_ptr
。如果由delete
管理的对象是从unique_ptr<Parent>
派生的类型,则会产生未定义的行为。因此,简而言之,您正在努力(无论是由谁设计的)第三方库的意图,并且,如果您无论如何都强迫代码进行编译,则报酬将是不确定的。