当我在C ++中定义一个类时,我总是将dtor定义为虚拟。 这是我保护自己的方法,以防我写一个继承类。
我想知道是否支付性能开销,即使我不会继承该类。
例如:
class A final
{
A();
virtual ~A(){printf("dtor");}
};
当我使用这个类时,dtor实际上是通过vtable调用还是实现为静态dtor?
答案 0 :(得分:4)
当我在C ++中定义一个类时,我总是将dtor定义为虚拟。
这是非常糟糕的做法。类应该被设计成多态的......或者不是。它不仅仅是设计问题 - 多态性增加了开销。
现在,好的编译员看到delete a;
,如果他们能证明a
只会是A
类型,那么就会删除虚拟来电并直接调用~A()
。这称为虚拟化。但他们不会做的就是删除vtable。添加不必要的多态性意味着你的所有类型现在都有vtable,这意味着它们都在使用额外的空间。在您的简单示例中,virtual
的存在会将sizeof(A)
从1增加到8.如果您有很多A
,那么您现在正在搞乱缓存效果。这很糟糕。
简而言之,根据用途设计课程。不是根据你可能会或可能没有的一些问题,如果他们被误用了。
这是我保护自己的方法,以防我写一个继承类。
另请注意,并非所有继承都必须是多态的 - 即使是要从中继承的类也不需要具有virtual
析构函数。只有在使用Base*
然后delete
时,才需要这样做。只要我不通过std::vector<>
尝试delete
我继承的类型,我就可以完全安全地继承std::vector<>
这样的内容来提供不同的界面。
另一方面,这个
class A final { ... };
是好习惯!如果A
不打算继承,那么明确地使它从一开始就不合格。现在,当你需要继承A
时,你必须有意识地考虑这样做的后果。
答案 1 :(得分:2)
只要您将类声明为final,就不能将其用作任何其他类的基类。所以虚拟没有意义。
由于好像规则,编译器可以随意忽略虚拟键盘,但不需要这样做。仅仅存在vtable是一个实现细节,并不是标准所要求的。
TL / DR:这取决于编译器的实现。