当前位置:  开发笔记 > 编程语言 > 正文

安全地覆盖C++虚函数

如何解决《安全地覆盖C++虚函数》经验,为你挑选了6个好方法。

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

举个例子:

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(),因为child的方法错过了const声明,因此声明了一个新方法.这也可能是函数名中的拼写错误或参数类型中的一些细微差别.如果基类的接口发生更改并且某些派生类未更新以反映更改,则也很容易发生.

有没有办法避免这个问题,我能以某种方式告诉编译器或其他工具为我检查这个吗?任何有用的编译器标志(最好是g ++)?你如何避免这些问题?



1> Gunther Piez..:

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

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;
};


必须在定义中使用@ h9uest`overit`.内联实现既是定义又是实现,所以没关系.

2> CB Bailey..:

像C#的override关键字不是C++的一部分.

在gcc中,-Woverloaded-virtual警告不要使用相同名称的函数隐藏基类虚函数,但是它不会覆盖它.但是,它不会保护您免于因错误拼写函数名称本身而无法覆盖函数.


有趣的是,在评论*使用VC++之后的几年内,没有"覆盖"一个关键字*它似乎*做*.好吧,不是一个合适的关键字,而是C++ 11中的特殊标识符.微软努力推动这个特殊情况,并遵循属性的一般格式和`覆盖`使其成为标准:)
使用Visual C++不会在C++中"覆盖"一个关键字; 但是,这可能意味着您正在使用可以编译一些无效C++源代码的东西.;)
覆盖无效的事实C++意味着标准是错误的,而不是Visual C++
如果您碰巧使用Visual C++
@Jon:好的,现在我看到你在开车了.我个人可以采取或离开C#样式`覆盖`功能; 我很少遇到覆盖失败的问题,而且它们相对容易诊断和修复.有人认为我不同意VC++用户应该使用它.我希望C++在所有平台上看起来都像C++,即使某个特定项目不需要是可移植的.值得注意的是,C++ 0x将具有`[[base_check]]`,`[[override]]`和`[[hiding]]`属性,因此如果需要,您可以选择覆盖检查.

3> Ray Hidayat..:

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

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

我以为我在www.parashift.com上看到你实际上可以实现一个抽象方法.这对我个人来说是有意义的,它唯一能做的就是强制子类来实现它,没有人说它不允许有自己的实现.


我同意Michael Burr的观点.制作基类摘要不是问题的一部分.在虚拟方法中使用具有功能的基类是非常合理的,您希望派生类重写.并且希望防止另一个程序员重命名基类中的函数,并导致派生类不再覆盖它也是合理的.在这种情况下,Microsoft"覆盖"扩展是非常宝贵的.我很乐意看到它添加到标准中,因为遗憾的是没有它就没有好办法做到这一点.

4> Doug..:

在MSVC中,override即使您没有编译CLR ,也可以使用CLR 关键字.

在g ++中,没有直接的方法可以在所有情况下执行; 其他人已经就如何捕捉签名差异给出了很好的答案-Woverloaded-virtual.在将来的版本中,有人可能会__attribute__ ((override))使用C++ 0x语法添加类似或等效的语法.



5> bobobobo..:

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

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

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



6> Tanveer Bada..:

使函数成为抽象,以便派生类除了覆盖它之外别无选择.

@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. */ }

推荐阅读
农大军乐团_697
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有