C++中使用unique_ptr处理含protected析构函数的第三方类报错求助
解决std::unique_ptr管理拥有protected析构函数类的问题
问题背景
你尝试用std::unique_ptr管理第三方库中拥有protected析构函数的Parent类对象时遭遇编译错误,核心原因是std::unique_ptr默认使用的std::default_delete会直接执行delete操作,而外部代码无法访问Parent的protected析构函数。你的示例代码如下:
#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(); // 此语句正常 std::unique_ptr<Parent> p2(get()); // 此语句报错 return 0; }
编译器报错的本质是:std::default_delete的operator()尝试调用Parent的析构函数,但该函数是protected权限,外部无法直接访问。
解决方案:自定义删除器
由于无法修改第三方库的Parent和Child类,我们可以给std::unique_ptr指定自定义删除器,利用Child的public析构函数完成对象销毁。
方法1:使用Lambda表达式作为删除器
这是最简洁的实现方式,直接在创建unique_ptr时定义删除逻辑:
int main(int argc, char const* argv[]) { Parent * p1 = get(); // 自定义删除器:将Parent*安全转为Child*后执行删除 std::unique_ptr<Parent, void(*)(Parent*)> p2(get(), [](Parent* ptr) { delete static_cast<Child*>(ptr); }); return 0; }
方法2:使用独立函数作为删除器
如果删除逻辑需要复用,可以单独定义删除函数:
// 自定义删除函数,可在多处复用 void delete_parent(Parent* ptr) { delete static_cast<Child*>(ptr); } int main(int argc, char const* argv[]) { Parent * p1 = get(); std::unique_ptr<Parent, decltype(&delete_parent)> p2(get(), delete_parent); return 0; }
方法3:使用std::function作为删除器类型(更灵活)
如果后续需要灵活调整删除逻辑,可以用std::function作为删除器类型:
#include <functional> // 需要包含此头文件 int main(int argc, char const* argv[]) { Parent * p1 = get(); std::unique_ptr<Parent, std::function<void(Parent*)>> p2(get(), [](Parent* ptr) { delete static_cast<Child*>(ptr); }); return 0; }
方案可行性说明
- 第三方库的
get()函数返回的是Child*转型为Parent*的指针,因此static_cast<Child*>(ptr)是类型安全的; Child的析构函数是public的,删除Child*时会先调用Child的析构,再自动触发Parent的protected析构——而子类Child有权访问父类的protected成员,因此这个调用是合法的。
内容的提问来源于stack exchange,提问作者alec.tu
相关产品推荐
相关产品推荐

