这两者之间有什么区别:
你什么时候用一个而不是另一个?
答案 0 :(得分:6)
当您将Base类方法声明为virtual
时,为了覆盖它,您需要在Derived类中提供具有完全相同签名的函数( Co-variant返回类型是虽然允许)。
如果你的函数名相同,但Derived类中的签名与Base类中的签名不同,那么它不再是overidding,它是 function Hiding ,派生类方法隐藏了Base类方法。
函数重载永远不会跨类,您可以在同一个类或自由函数中重载方法,但不能跨类。当你尝试跨类时,你最终得到的是函数隐藏。
要将Base类方法放在Derived类的范围内,您需要添加一个
附加using functionName
到您的Derived类。
修改强>
关于何时使用virtual
超载的Q,答案是:
如果您打算为运行时多态性覆盖您的类的函数,则应将它们标记为virtual
,如果您不打算这样做则不会。
答案 1 :(得分:3)
重载完全独立于(正交)虚拟覆盖。
在覆盖中,一个函数被另一个相同的签名替换。然后有一些规则来挑选最重要的"函数,虚函数表示在派生程度最高的类中定义的函数。作为虚函数的特殊情况,签名的返回类型可能略有不同(协方差)。
在重载时,具有不同参数类型的函数签名同时充当进行函数调用时要选择的候选者。选择合适的规则有一套非常复杂的规则,这种规则在95%的情况下运作良好,并且在不合作的时候让你头疼。
由于重载适用于不同的签名和覆盖相同签名的作品,因此它们并不会相互干扰。
您可以将基类的函数显式导入派生类,以扩展重载的函数名称。这是由派生类中的using base_class::overload_name;
完成的。
答案 2 :(得分:0)
我相信你的意思是重写非虚函数而不是重载。当您在派生类中覆盖非虚基类函数时,将在编译时解析并绑定对函数的调用。这意味着函数调用是根据调用函数的类型(或指针)解决的。如果要在基类指针上调用该函数,则始终调用基类版本。如果使用派生类指针,则始终调用派生版本;不管它指向的实际对象。
如果基类版本标记为虚拟,则调用解析或绑定将在运行时根据调用对象的类型而不是基于用于生成的指针类型而延迟电话。这意味着您可以使用基类指针指向基类和派生类对象,然后调用该函数。根据指针指向的对象类型,调用相应的函数版本。这意味着如果我的指针指向基类对象,则调用基类版本。如果指针指向派生类型对象,则调用派生的verion。