C++如果派生中没有数据成员,是否还需要虚拟析构函数?

发布于 2024-09-27 07:51:21 字数 332 浏览 7 评论 0原文

假设我有这段代码,

class Base{
  public:
        int getVal();
  private:
         int a, b;
};

class Derived::public Base{
    public:
         void printVal();
};

int main(){
    Base *b = new Derived();
    delete b;    
}

我知道虚拟析构函数会正确删除内容,但是即使派生类中没有虚拟函数和数据成员,使用基指针删除(当没有虚拟析构函数时)是否不好?如果这样做会发生什么?

Suppose I have this code

class Base{
  public:
        int getVal();
  private:
         int a, b;
};

class Derived::public Base{
    public:
         void printVal();
};

int main(){
    Base *b = new Derived();
    delete b;    
}

I know a virtual destructor would delete things properly, but is it bad to delete with base pointer (when there is no virtual destructor) even if there are no virtual functions and no data members in the derived class? What will happen if this is done?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

生生漫 2024-10-04 07:51:21

即使派生类中没有虚函数和数据成员,用基指针删除(没有虚析构函数时)是否不好?

是的。

无论派生类的内容如何,​​该行为都是未定义的。

如果这样做会发生什么?

什么事情都可能发生。

Is it bad to delete with base pointer (when there is no virtual destructor) even if there are no virtual functions and no data members in the derived class?

Yes.

The behavior is undefined regardless the contents of the derived class.

What will happen if this is done?

Anything could happen.

我不是你的备胎 2024-10-04 07:51:21

对于原始类型数据,您的示例很可能在实践中有效。事实上,引入 vtable 实际上可能阻碍性能(因此这里可能有一些合法的用途),但根据 5.3-5.4,它在技术上是未定义的:

如果操作数的静态类型[of
删除运算符] 不同于
它的动态类型、静态类型
应是操作数的基类
动态类型和静态类型应
有一个虚拟析构函数或
行为未定义。

这实际上完全取决于类中数据的“堆”,并且由于没有堆分配的成员(在您的情况下),所以您应该没问题,但这绝对是代码味道。

For primitive-type data, your example will most likely work in practice. As a matter of fact, incurring a vtable could actually hinder performance (so there may be some legitimate use here), but it is technically undefined, per 5.3-5.4:

If the static type of the operand [of
the delete operator] is different from
its dynamic type, the static type
shall be a base class of the operand's
dynamic type and the static type shall
have a virtual destructor or the
behaviour is undefined.

It really all depends on the "heapness" of the data in your class, and as there are no heap-allocated members (in your case), you should be fine, but it's definitely a code smell.

深爱成瘾 2024-10-04 07:51:21

当通过指向基类的指针创建派生对象时,为了正确调用派生析构函数(多态性),派生类中需要虚拟析构函数。

高完整性 CPP 规则 3.3.2 为基类编写“虚拟”析构函数。 (QACPP 2116)

理由:如果一个对象将通过指向其基类的指针被销毁,那么该基类应该有一个虚拟析构函数。如果基类析构函数不是虚拟的,则仅调用基类的析构函数。在大多数情况下,析构函数应该是虚拟的,因为维护或重用可能会添加需要虚拟析构函数的派生类。

class Base {}; 
class Derived : public Base { public: ~Derived() {} }; 

void foo() {  
   Derived* d = new Derived; delete d; // correctly calls derived destructor 
} 
void boo() { 
   Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor! 
}

The virtual desctructor in the derived class is needed in order to properly call the derived destructor (polymorphism), when the derived object is created through a pointer to the base class.

High Integrity CPP Rule 3.3.2 Write a 'virtual' destructor for base classes. (QACPP 2116)

Justification: If an object will ever be destroyed through a pointer to its base class, then that base class should have a virtual destructor. If the base class destructor is not virtual, only the destructor for the base class will be invoked. In most cases, destructors should be virtual, because maintenance or reuse may add derived classes that require a virtual destructor.

class Base {}; 
class Derived : public Base { public: ~Derived() {} }; 

void foo() {  
   Derived* d = new Derived; delete d; // correctly calls derived destructor 
} 
void boo() { 
   Derived* d = new Derived; Base* b = d; delete b; // problem! does not call derived destructor! 
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文