- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
据我所知,任何被指定为具有子类的类都应该使用虚拟析构函数声明,这样在通过指针访问它们时可以正确地销毁类实例。
但是为什么甚至可以用非虚拟析构函数声明这样的类呢?我相信编译器可以决定何时使用虚拟析构函数。那么,这是 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/
我是一名优秀的程序员,十分优秀!