基类没有析构函数,但派生类有析构函数。我是否需要寻找与堆无关的任何陷阱?
Base class has no destructor, but derived class does. Do I need to look for any pitfalls that DON'T relate to the heap?
在继承方面,我知道建议类的析构函数是虚拟的,因此除了任何派生析构函数之外,还可以正确调用基类的析构函数。但是,我想知道在以下情况下是否存在与派生对象相关的堆栈相关问题。
假设我们有一个没有析构函数的基类(无论出于何种原因):
class Base{};
以及一个确实具有析构函数的派生类:
class Derived : public Base
{
~Derived(){}
};
而且主要...:
int main()
{
Derived a;
return 0;
}
我是否遇到基类没有析构函数的任何问题?我最初的猜测是编译器只会为 Base 类生成一个默认析构函数。同样,我的问题主要与堆栈而不是动态内存有关:为了避免调用派生析构函数而 Base 析构函数不被调用,我是否需要注意任何奇怪的场景?
您正在考虑的规则是,如果通过指向派生类型的一个基类型的指针删除该对象,并且该基类型没有虚拟析构函数,则行为是未定义的。此处的代码不会删除任何内容,因此该规则不适用。
为了确保安全,每个析构函数(隐式或显式)至少是以下之一就足够了:
-
virtual
(如果需要通过基类指针删除子类实例,则用于基类) -
protected
(确保无法尝试通过基类指针删除) -
final
(实际上是类的一个属性,以避免子类的全部可能性)。
在少数情况下,可以安全地调用析构函数,但它们通常是设计不良的标志,如果您设法遇到其中一个,则很容易避免。
顺便说一句,请注意,std::shared_ptr
类型擦除其删除器,因此即使Base
没有公共析构函数,std::shared_ptr<Base>
也可以工作。
基类有一个隐式析构函数。一切都会好起来的。
虚拟基类析构函数用于允许派生构造函数在通过指针或对基类的引用进行析构时运行。因此,在您的情况下,这将是不安全的:
void destruct(Base &b) { b.~Base(); }
Derived d; destruct(d);
但这将是完全安全的:
void destruct(Derived &d) { d.~Derived(); }
Derived d; destruct(d);
相关文章:
- 什么时候调用组成单元对象的析构函数
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 内联映射初始化的动态atexit析构函数崩溃
- 什么时候调用析构函数
- 优先顺序:智能指针和类析构函数
- C++-明确何时以及如何调用析构函数
- 使用基类指针创建对象时,缺少派生类析构函数
- 在c++中使用向量时,如何调用构造函数和析构函数
- 重载运算符new[]的行为取决于析构函数
- 我需要知道编译器如何在cpp中使用析构函数
- 为什么在使用转换构造函数赋值后调用C++类的析构函数?
- 析构函数调用
- 通过引用传递-为什么要调用这个析构函数
- 对具有动态分配的内存和析构函数的类对象的引用
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- C++成员的析构函数顺序与shared_ptr
- C++ 防止在映射中放置()时调用析构函数
- 在这种情况下显式调用时,std::cout 如何更改析构函数的行为?
- 调用析构函数以释放动态分配的内存
- 基类没有析构函数,但派生类有析构函数。我是否需要寻找与堆无关的任何陷阱?