关于c ++:重载Virtual方法与Non-Virtual方法有何不同?

How does overloading a Virtual method differ from a Non-Virtual method?

这两者有什么区别:

  • 声明基类函数virtual并更改派生类功能。
  • 重载继承的非虚拟函数。

你什么时候用一个比另一个?


当您有一个声明为virtual的基类方法时,为了重写它,您需要在派生类中提供一个具有完全相同签名的函数(但是允许使用同变量返回类型)。

如果您的函数名相同,但派生类中的签名与基类中的签名不同,那么它不再是过度标识,而是函数隐藏,派生类方法隐藏了基类方法。

函数重载永远不是交叉类,可以在同一类或自由函数内重载方法,但不能重载交叉类。当你试图通过类来实现它时,你最终得到的是函数隐藏。

要使基类方法在派生类的范围内,需要添加附加的using functionName到派生类。

编辑:关于何时使用virtual过载的问题,答案是:如果您希望类的函数因运行时多态性而被重写,那么应该将它们标记为virtual,如果您不打算这样做,则不应标记为virtual

良好阅读:何时将C++中的函数标记为虚拟?


重载完全独立于(正交到)虚拟重写。

在重写中,一个函数替换为另一个具有相同签名的函数。然后有一些规则来选择"最重要"的函数,对于虚拟函数来说,这意味着在最派生类中定义的函数。作为虚拟函数的一种特殊情况,签名的返回类型可能略有不同(协方差)。

在重载中,在进行函数调用时,具有不同参数类型的函数签名同时充当要选择的候选者。有一套非常复杂的规则来选择正确的规则,95%的时候都能很好地工作,如果不合作的话会让你头疼。

由于重载使用不同的签名,而重写使用相同的签名,因此它们不会真正互相干扰。

可以将基类的函数显式导入派生类,以便扩展重载的函数名。这是由派生类中的using base_class::overload_name;完成的。


我相信您的意思是重写非虚拟函数,而不是重载。当重写派生类中的非虚拟基类函数时,对该函数的调用将在编译时解析并绑定。这意味着函数调用是基于调用函数的类型(或指针)来解析的。如果在基类指针上调用函数,则始终调用基类版本。如果使用派生类指针,则始终调用派生版本;而不考虑它指向的实际对象。

如果基类版本标记为虚拟,则调用解析或绑定将延迟到运行时根据调用所基于的对象类型进行,而不是根据用于进行调用的指针类型进行。这意味着您可以使用基类指针指向基类和派生类对象,然后调用函数。根据指针指向的对象类型,调用相应的函数版本。这意味着,如果我的指针指向基类对象,那么将调用基类版本。如果指针指向派生类型对象,则调用派生verion。