【问题标题】:Behavior of virtual function in C++C++ 中虚函数的行为
【发布时间】:2010-04-19 17:58:56
【问题描述】:

我有一个问题,下面是两个类:

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

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

问题是:

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

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

【问题讨论】:

  • 这是可选的,但有些人认为明确覆盖成员函数是一种良好的风格。

标签: c++ virtual-functions


【解决方案1】:

C++03 §10.3/2:

如果一个虚成员函数 vf 是 在类 Base 和 类派生,直接派生或 间接来自成员 Base 具有相同名称的函数 vf 和 与 Base::vf 相同的参数列表是 声明,则 Derived::vf 也是 虚拟的(不管是不是这样 声明) 并覆盖 基地::vf。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 对编译器没有影响。对于人类读者来说,它实际上可以提高可读性。我总是在所有继承级别明确声明 virtual。
    【解决方案3】:

    virtual 属性是从基类继承而来的,即使您不输入它也会被假定存在。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 有人可能会补充说,它可能会对人类读者产生影响。
      【解决方案5】:

      一个函数一次是虚的,永远是虚的

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

      • 如果函数/方法应该 被覆盖,总是使用 “虚拟”关键字。这尤其 在接口/基础中使用时为真 类。
      • 如果派生类应该 进一步明确地细分 为每个声明“虚拟”关键字 可以的功能/方法 被覆盖。
      • 如果派生的函数/方法 类不应该是 再次子分类,然后是关键字 'virtual' 将被评论 表示函数/方法 被覆盖但没有 覆盖它的其他类 再次。这当然不妨碍 有人从压倒一切 派生类,除非该类 是最终的(不可推导的),但它 表示该方法不应该是 被覆盖。 例如:/*virtual*/ void someFunc();

      【讨论】:

      • 对于“总是被覆盖”的情况,可能还需要添加纯说明符。
      • 我认为“覆盖”和“总是”之间应该有一个逗号。即“始终使用 virtual 关键字”而不是“始终覆盖”。
      • @Myke:除了 pure 不是 C++ 关键字。
      • “纯说明符”的形式为 = 0,而不是关键字。
      • @Myke:好吧,好吧。谁会想到...我没有,反正。 :)
      【解决方案6】:

      您是否在函数的派生版本上提供 virtual 关键字对 编译器 来说并不重要。

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

      【讨论】:

        【解决方案7】:

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

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-07-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-11-02
          • 1970-01-01
          相关资源
          最近更新 更多