102

我有一个带有虚函数的基类,我想在派生类中重写该函数。有没有办法让编译器检查我在派生类中声明的函数是否实际上覆盖了基类中的函数?我想添加一些宏或其他东西,以确保我不会意外声明一个新函数,而不是覆盖旧函数。

举个例子:

class parent {
public:
  virtual void handle_event(int something) const {
    // boring default code
  }
};

class child : public parent {
public:
  virtual void handle_event(int something) {
    // new exciting code
  }
};

int main() {
  parent *p = new child();
  p->handle_event(1);
}

这里parent::handle_event()被调用而不是child::handle_event(),因为孩子的方法错过了const声明,因此声明了一个新方法。这也可能是函数名称的拼写错误或参数类型的一些细微差别。如果基类的接口发生更改并且某些派生类未更新以反映更改,也很容易发生这种情况。

有什么方法可以避免这个问题,我可以告诉编译器或其他工具帮我检查吗?任何有用的编译器标志(最好是 g++)?你如何避免这些问题?

4

10 回答 10

91

从 g++ 4.7 开始,它确实理解新的 C++11override关键字:

class child : public parent {
    public:
      // force handle_event to override a existing function in parent
      // error out if the function with the correct signature does not exist
      void handle_event(int something) override;
};
于 2012-07-23T09:37:00.913 回答
20

像 C# 的override关键字这样的东西不是 C++ 的一部分。

在 gcc 中,-Woverloaded-virtual警告不要隐藏具有相同名称但签名完全不同的函数的基类虚函数,它不会覆盖它。但是,它不会保护您不会因为函数名称本身拼写错误而无法覆盖函数。

于 2009-01-30T23:31:01.793 回答
18

据我所知,你不能把它抽象化吗?

class parent {
public:
  virtual void handle_event(int something) const = 0 {
    // boring default code
  }
};

我以为我在 www.parashift.com 上读到过,您实际上可以实现一个抽象方法。这对我个人来说是有道理的,它唯一做的就是强制子类实现它,没有人说它不允许自己实现。

于 2009-01-30T23:32:24.443 回答
11

override在 MSVC 中,即使不是为 CLR 编译,也可以使用 CLR关键字。

在 g++ 中,没有直接的方法可以在所有情况下强制执行。其他人就如何使用-Woverloaded-virtual. 在未来的版本中,有人可能会__attribute__ ((override))使用 C++0x 语法添加类似或等效的语法。

于 2009-01-31T00:26:23.633 回答
9

在 MSVC++ 中,您可以使用关键字override

class child : public parent {
public:
  virtual void handle_event(int something) <b>override</b> {
    // new exciting code
  }
};

override适用于 MSVC++ 中的本机代码和 CLR 代码。

于 2011-07-16T18:55:23.943 回答
5

使函数抽象化,以便派生类除了重写它之外别无选择。

@Ray 您的代码无效。

class parent {
public:
  virtual void handle_event(int something) const = 0 {
    // boring default code
  }
};

抽象函数不能具有内联定义的主体。必须修改为

class parent {
public:
  virtual void handle_event(int something) const = 0;
};

void parent::handle_event( int something ) { /* do w/e you want here. */ }
于 2009-01-31T07:56:38.467 回答
3

我建议对您的逻辑稍作改动。它可能会或可能不会起作用,这取决于您需要完成的工作。

handle_event() 仍然可以执行“无聊的默认代码”,但不是虚拟的,而是在您希望它执行“新的令人兴奋的代码”时让基类调用抽象方法(即必须重写)方法这将由您的后代班级提供。

编辑:如果您后来决定您的某些后代类不需要提供“新的令人兴奋的代码”,那么您可以将抽象更改为虚拟并提供该“插入”功能的空基类实现。

于 2009-01-30T23:12:45.293 回答
2

如果基类函数被隐藏,您的编译器可能会生成一个警告。如果是,请启用它。这将捕获参数列表中的 const 冲突和差异。不幸的是,这不会发现拼写错误。

例如,这是 Microsoft Visual C++ 中的警告 C4263。

于 2009-01-30T23:17:45.753 回答
1

当C++11override关键字与派生类中的函数声明一起使用时,它会强制编译器检查声明的函数是否实际上覆盖了某些基类函数。否则,编译器会抛出错误。

因此,您可以使用override说明符来确保动态多态性(函数覆盖)。

class derived: public base{
public:
  virtual void func_name(int var_name) override {
    // statement
  }
};
于 2019-10-07T15:14:00.557 回答
0
class MyClass {
public:
 
  MyClass() {}
  virtual uint32_t someFunction(bool param = false) {
    if (param) {
      std::cout << "This is an example virtual function with default code" << std::endl;
    }
    return 1100;  //just for return something
  };

 
  • 然后您可以根据需要覆盖该功能
class MyClass2 : public MyClass  {
public:
  MyClass2();
  uint32_t someFunction(bool param) override;
};


uint32_t MyClass2::someFunction(bool verbose) {
  std::cout << "This is new implementation for virtual method " << std::endl;

}

于 2021-06-13T01:48:56.710 回答