如果没有类重新实现它,可以优化'virtual'关键字吗?

时间:2016-05-20 11:15:22

标签: c++ inheritance virtual vtable

当我在C ++中定义一个类时,我总是将dtor定义为虚拟。 这是我保护自己的方法,以防我写一个继承类。

我想知道是否支付性能开销,即使我不会继承该类。

例如:

class A final
{
    A();
    virtual ~A(){printf("dtor");}
};

当我使用这个类时,dtor实际上是通过vtable调用还是实现为静态dtor?

2 个答案:

答案 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:这取决于编译器的实现。