可以';虚拟';如果没有类重新实现关键字,它会被优化掉吗? 当我在C++中定义类时,我总是将Dor定义为虚拟的。 这是我保护自己的方法,以防编写继承类

可以';虚拟';如果没有类重新实现关键字,它会被优化掉吗? 当我在C++中定义类时,我总是将Dor定义为虚拟的。 这是我保护自己的方法,以防编写继承类,c++,inheritance,virtual,vtable,C++,Inheritance,Virtual,Vtable,我想知道我是否会支付性能开销,即使我不会继承这个类 例如: class A final { A(); virtual ~A(){printf("dtor");} }; 当我使用这个类时,dtor实际上是通过vtable调用的还是作为静态dtor实现的?一旦您将该类声明为final,它就不能用作任何其他类的基类。因此,虚拟世界毫无意义 由于“仿佛”规则,编译器可以随意忽略虚拟键盘,但不需要这样做。顺便说一句,vtable的存在只是一个实现细节,而不是标准所要求的 TL/DR:这取

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

例如:

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

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

一旦您将该类声明为final,它就不能用作任何其他类的基类。因此,虚拟世界毫无意义

由于“仿佛”规则,编译器可以随意忽略虚拟键盘,但不需要这样做。顺便说一句,vtable的存在只是一个实现细节,而不是标准所要求的

TL/DR:这取决于编译器实现

当我在C++中定义类时,我总是将Dor定义为虚拟的。p> 这是非常糟糕的做法。类应该被设计为多态的。。。或者不是。这也不仅仅是设计问题——多态性增加了开销

现在,好的编译器看到
删除一个
如果他们能够证明
a
将只属于
a
类型,则将删除虚拟调用并直接调用
~a()
。这就是所谓的去虚拟化。但他们不会移除vtable。添加不必要的多态性意味着所有类型现在都有vtables,这意味着它们都在使用额外的空间。在您的简单示例中,
virtual
的存在将
sizeof(A)
从1增加到8。如果你有很多
a
s,那么你现在正在处理缓存效果。这很糟糕

简而言之,根据类的用途设计类。而不是根据一些问题,如果它们被滥用,你可能最终会或可能不会遇到这些问题

这是我保护自己的方法,以防编写继承类

还要注意的是,并非所有的继承都必须是多态的——即使是打算从中继承的类也不需要有一个
virtual
析构函数。只有当用法是保留一个
Base*
然后
删除它时,才需要这样做。只要我不想通过
std::vector
删除继承的类型,就可以从
std::vector
这样的东西继承来提供一个不同的接口,这是非常安全的


另一方面

class A final { ... };

这是个好习惯!如果
A
不打算从中继承,那么显式地使从中继承的格式错误。现在,当您需要从
A
继承时,您必须有意识地考虑这样做的后果

好问题,但我个人不建议在这里默认编写
virtual
。仅当类中还有其他虚拟函数时才使用它,否则它就没有用处。另外,您可以通过分析代码来回答这个问题。这类测试既有趣又有趣。我认为在基类的dtor中忘记“virtual”关键字的“代价”比通过vtable调用代码中每个dtor的“代价”要糟糕得多。我刚刚看到您使用了
final
,在这种情况下,您绝对不应该将函数标记为
virtual
。但是,即使没有
final
,如果您不需要,添加
virtual
也是不好的做法。但是,通常创建/存在类的目的就是为了得到扩展。否则,可以使用POD <代码>结构> /CODE。@ SAMErkn引用。@ SAMErkn:C++中,<代码> Stutt定义了一个类。我不是在开玩笑,这才是真正的语言规范<代码>结构
仅影响成员的默认访问,直到第一个显式访问说明符。
final
关键字有意义,如果唯一的目的是将
用作存储数据和函数的紧凑实体,从而提供对这些数据的访问。@sameerkn类级别上的
final
关键字与
虚拟
函数和
final
关键字。类可以是非
final
,以允许将来添加成员和方法,而不必包含
虚拟
析构函数或任何其他虚拟方法。将析构函数声明为
virtual
,如果该类(根据Murphy,而不是Machiavelli)永远不能通过指向其基类之一的指针删除,则总是为您不使用的东西付费。在它永远无法被重写的情况下,将其虚拟化是毫无意义的,这是一种自相矛盾的程度。从技术上讲,编译器也可以将vtables用于非多态类。这方面的主要问题是为vptr找到一个位置。