如何使用父类类型的智能指针调用子类的析构函数
How to call the destructor of child class with a smart pointer of parent type?
在我的应用程序中,我曾经有一个unique_ptr<parent> _member
作为自定义类的成员。代码运行良好。然而,当我最近试图创建另一个从parent
类继承的类,并在构造函数中使用_member = unique_ptr<child>(new child())
初始化_member
时,我意识到当自定义类被销毁时,_member
的析构函数只调用父析构函数,但现在调用子析构函数。
这个行为对我来说是有意义的。因为毕竟_member
的类型是unique_ptr<parent>
。然而,我想知道我只给_member
调用子析构函数的选项是什么。
行为没有意义。如果child的析构函数需要释放内存,而没有调用它,就会导致内存泄漏。
Parent需要有一个虚析构函数,以便在通过指向父类的指针删除派生类时调用派生类的析构函数。
经验法则:如果基类至少有一个虚函数,它应该有一个虚析构函数
除了尼尔的好答案,还有另一条路你可以走。
如果您使用std::shared_ptr
而不是std::unique_ptr
,您将获得std::shared_ptr
的类型擦除特性的好处。让我们看一个例子:
#include <memory>
#include <iostream>
struct X {
~X() {
std::cout << __PRETTY_FUNCTION__ << "n";
}
};
struct Y : X {
~Y() {
std::cout << __PRETTY_FUNCTION__ << "n";
}
};
int main() {
std::shared_ptr<X> obj = std::make_shared<Y>();
}
这段代码,运行时会输出:
Y::~Y()
X::~X()
我将使父类析构函数为虚函数。如果您有一个用例需要正确销毁没有虚函数的类,并且您不想使用std::shared_ptr
的类型擦除销毁功能,则可以使用unique_ptr
和自定义删除器实现相同的功能:
template <typename T>
void delete_function(void* ptr) {
// Tell GCC that we know we're doing something stupid and
// it need not warn us about it.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdelete-non-virtual-dtor"
delete static_cast<T*>(ptr);
#pragma GCC diagnostic pop
}
template <typename T>
using erased_unique_ptr = std::unique_ptr<T, void(*)(void*)>;
template <typename T, typename... Args>
inline erased_unique_ptr<T>
make_unique_erased(Args&&... args) {
return erased_unique_ptr<T>(new T(std::forward<Args>(args)...), &delete_function<T>);
}
观看Coliru现场直播
相关文章:
- C++继承,如何在基类的方法中调用子类的方法?
- 无法调用子类函数,C++
- 我可以从我的超类调用子类构造函数吗?
- 基类中的虚拟方法和子类中的非 Virtula 方法.仍然如何调用子类方法,即使它是非虚拟的
- 错误:调用"子类::..."没有匹配函数
- 调用子类函数
- 当不处理指针时,请调用子类(虚拟)函数(较晚绑定)
- 调用子类方法会导致分段错误
- 当调用子类的析构函数时,是否也会调用父类的析构函数
- 继承基类,定义基类的原型方法,但从第三个对象调用子类的方法
- 如何在不知道C++中基类名称的情况下调用子类中基类的成员
- 以错误的方式调用子类中的函数的最佳方法是什么
- C++ 无法使用指向类的指针调用子类方法e
- c++ 调用子类而不是父类的重写函数
- 调用子类化 QWidget 的方法
- 继承/多态性-调用子类的方法
- 为什么没有调用子类的虚拟函数
- 遗产.从父类调用子类函数
- 从主类调用子类
- 从SuperClass C调用子类方法