gpt4 book ai didi

c++ - 使用非虚拟析构函数有什么具体原因吗?

转载 作者:IT老高 更新时间:2023-10-28 21:56:42 29 4
gpt4 key购买 nike

据我所知,任何被指定为具有子类的类都应该使用虚拟析构函数声明,这样在通过指针访问它们时可以正确地销毁类实例。

但是为什么甚至可以用非虚拟析构函数声明这样的类呢?我相信编译器可以决定何时使用虚拟析构函数。那么,这是 C++ 设计疏忽,还是我遗漏了什么?

最佳答案

Are there any specific reasons to use non-virtual destructors?

是的,有。

主要归结为性能。虚函数不能被内联,相反,您必须首先确定要调用的正确函数(这需要运行时信息),然后再调用该函数。

在性能敏感的代码中,无代码和“简单”函数调用之间的区别可能会有所不同。与许多语言不同,C++ 并不认为这种差异是微不足道的。

But why it's even possible to declare such class with non-virtual destructor?

因为(对于编译器)很难知道类是否需要虚拟析构函数。

在以下情况下需要虚拟析构函数:

  • 您在指针上调用 delete
  • 通过基类到派生对象

当编译器看到类定义时:

  • 它不知道你打算从这个类派生——你毕竟可以从没有虚拟方法的类派生
  • 但更可怕的是:它不知道你打算在这个类上调用 delete

许多人认为多态性需要更新实例,这只是缺乏想象力:

class Base { public: virtual void foo() const = 0; protected: ~Base() {} };

class Derived: public Base {
public: virtual void foo() const { std::cout << "Hello, World!\n"; }
};

void print(Base const& b) { b.foo(); }

int main() {
Derived d;
print(d);
}

在这种情况下,不需要为虚拟析构函数付费,因为在析构时不涉及多态性。

归根结底,这是一个哲学问题。在可行的情况下,C++ 默认选择性能和最少的服务(主要的异常(exception)是 RTTI)。


关于警告。有两个警告可以用来发现问题:

  • -Wnon-virtual-dtor (gcc, Clang): 每当具有虚函数的类没有声明虚析构函数时发出警告,除非基类中的析构函数是 protected 。这是一个悲观的警告,但至少你不会错过任何东西。

  • -Wdelete-non-virtual-dtor(Clang,也移植到 gcc):每当调用 delete 时发出警告指向具有虚函数但没有虚析构函数的类的指针,除非该类被标记为 final。它的误报率为 0%,但会发出“迟到”的警告(可能会多次)。

关于c++ - 使用非虚拟析构函数有什么具体原因吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8697866/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com