使用 unique_ptr 保护析构函数

ale*_*.tu 1 c++

我正在尝试从第三方库调用 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;
}
Run Code Online (Sandbox Code Playgroud)

我正在尝试将 unique_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;
Run Code Online (Sandbox Code Playgroud)

关于摆脱这个问题的任何想法?我无法破解父子类,因为它们是第三方库的类。

Max*_*kin 5

您可以结交std::default_delete<Parent>朋友Parent来修复该错误。并且您可能还希望在通过指针访问派生类~Parent virtual时避免未定义的行为。deleteParent

例如:

class Parent { 
    friend class std::default_delete<Parent>;
    // ...
protected:
    virtual ~Parent();
    // ...
Run Code Online (Sandbox Code Playgroud)

但是,Parent设计清楚地表明您不应该delete通过Parent指针,这就是析构函数是非公开的。阅读Virtuality了解更多详情:

准则#4:基类析构函数应该是public 和virtual,或者protected 和nonvirtual。


你可能想引入另一个中间基类来解决这个问题:

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();
}
Run Code Online (Sandbox Code Playgroud)

  • @alec.tu 在这种情况下,你不应该通过 `Parent` 指针删除,这就是析构函数是非公开的。 (3认同)