10

我有一个问题,这里有两个类:

  class Base{
      public:
          virtual void toString();       // generic implementation
  }

  class Derive : public Base{
      public:
          ( virtual ) void toString();   // specific implementation
  }

问题是:

  • 如果我想派生类的子类使用Base类型的指针执行多态性,括号中的关键字 virtual 是否必要?

  • 如果答案是否定的,那么带和不带 virtual的Derive类的成员函数toString有什么区别?

4

7 回答 7

13

C++03 §10.3/2:

如果虚成员函数 vf 在类 Base 和 Derived 类中声明,直接或间接从 Base 派生,则声明与 Base::vf 具有相同名称和相同参数列表的成员函数 vf,则Derived::vf也是虚拟的(无论它是否如此声明)并且它覆盖 Base::vf。

于 2010-04-19T19:33:41.697 回答
10

那里的关键字是严格可选的,根本没有区别。

于 2010-04-19T18:00:45.393 回答
7

virtual属性是从基类继承的,即使您不键入它,也假定它存在。

于 2010-04-19T18:02:55.630 回答
1

一个函数曾经是一个 virtual 总是一个 virtual

因此,无论如何,如果在后续类中未使用 virtual 关键字,它不会阻止函数/方法成为“虚拟”,即被覆盖。因此,从团队发展的角度来看,以下指南可能会有所帮助:-

  • 如果应该重写函数/方法,请始终使用“虚拟”关键字。在接口/基类中使用时尤其如此。
  • 如果派生类应该是子类进一步明确声明可以覆盖的每个函数/方法的“虚拟”关键字。
  • 如果派生类中的函数/方法不应该再次被子类化,则要注释关键字“virtual”,表明该函数/方法已被覆盖,但没有其他类再次覆盖它。这当然不会阻止某人在派生类中重写,除非该类是最终的(不可派生的),但它表明该方法不应该被重写。前任:/*virtual*/ void someFunc();
于 2010-04-19T18:13:01.710 回答
1

编译器已经从基类中的 'virtual' 关键字知道 toString 是一个虚拟方法。无需重复。

于 2010-04-19T18:03:26.827 回答
0

这是一个好的风格问题,用户程序员知道发生了什么。在 C++0x 中,您可以使用 [[override]] 使其更加明确和可见。您可以使用 [[base_check]] 来强制使用 [[override]]。

如果您不想或不能这样做,只需使用 virtual 关键字。

如果在没有虚拟 toString 的情况下进行派生,并且将 Derive 的实例强制转换回 Base,则调用 toString() 实际上会调用 Base 的 toString(),因为据它所知,这是 Base 的实例。

于 2010-04-20T00:34:35.543 回答
0

无论您是否在函数的派生版本上提供virtual关键字,编译器都无关紧要。

但是,无论如何提供它是一个好主意,这样任何查看您的代码的人都可以知道它是一个虚函数。

于 2010-04-19T20:46:59.130 回答