何时将C++中的函数标记为虚拟函数

When to mark a function in C++ as a virtual?

本文关键字:函数 虚拟 记为 C++ 何时      更新时间:2023-10-16

由于方法静态绑定的C++特性,这会影响多态调用。

来自维基百科:

尽管这种调度机制所涉及的开销很低对于某些应用领域来说,该语言可能仍然很重要是为目标而设计的。因此,Bjarne StroustrupC++的设计者,选择使动态调度成为可选的非默认。只有使用virtual关键字声明的函数才会基于对象的运行时类型进行调度;其他功能将基于对象的静态类型进行调度。

所以代码:

Polygon* p = new Triangle;
p->area();

如果area()是Parent类中的non-virtual函数,而Child类中的是overridden,则上面的代码将调用开发人员可能不期望的Parent's class method。(感谢我介绍的静态绑定(

那么,如果我想写一个供其他人使用的类(例如库(,我是否应该让我的所有函数都是虚拟的,以便之前的代码按预期运行

简单的答案是,如果您打算为运行时多态性覆盖类的函数,则应该将它们标记为virtual,如果您不打算这样做,则不应该这样做。

不要仅仅因为觉得函数赋予了额外的灵活性就将其标记为virtual,而是要考虑您的设计和公开接口的目的。例如:如果你的类不是为了继承而设计的,那么让你的成员函数成为虚拟函数会产生误导。这方面的一个很好的例子是标准库容器,它不是要继承的,因此它们没有虚拟析构函数。

没有理由不将所有成员函数标记为虚拟的,引用一些性能惩罚、非POD类类型等等,但如果你真的认为你的类是运行时过度加载的,那么这就是它的目的,也是所谓的缺陷。

如果派生类应该能够覆盖该方法,则将其标记为虚拟。就这么简单。

就内存性能而言,如果有任何东西是虚拟的,那么您会得到一个虚拟指针表,因此查看它的一种方法是"please one,please all"。否则,正如其他人所说,如果你希望它们是可重写的,那么就把它们标记为虚拟的,这样在基类上调用该方法就意味着运行了专门的版本。

作为一般规则,只有当类被明确设计为用作基类,并且该函数被设计为被重写时,才应将函数标记为virtual。在实践中,大多数虚拟函数在基类中将是纯虚拟的。除了在调用反转的情况下,明确不为覆盖函数提供约定,虚拟函数应该是私有的(或者最多是受保护的(,并用强制约定的非虚拟函数封装。

基本上就是这个想法;实际上,如果您使用的是父类,我认为您不需要覆盖所有方法,所以如果您认为将以这种方式使用,只需将它们设为virtual即可。