2009-01-30 106 views
92

我有一个虚函数的基类,我想在派生类中重写该函数。有什么方法可以让编译器检查我在派生类中声明的函数是否实际覆盖了基类中的函数?我想添加一些宏,或者确保我没有意外声明一个新函数,而不是覆盖旧函数。安全地覆盖C++虚函数

拿这个例子:

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 ++)?你如何避免这些问题?

+2

大的问题,我一直在试图找出为什么我的孩子上课功能没有按,因为现在是一个t时刻被调用! – 2014-12-16 00:52:04

回答

78

由于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; 
}; 
3

我会建议你的逻辑略有改变。它可能会或可能不会工作,这取决于你需要完成什么。我们可以使用handle_event()仍然可以做“无聊的默认代码”,但不是虚拟的,在你希望它做“新兴奋代码”的地方,基类调用抽象方法(即必须是-overridden)方法将由您的后代类提供。

编辑:如果您稍后决定你的一些子类的做需要提供“新的令人兴奋的代码”,那么你可以抽象更改到虚拟化和提供一个空基类实现的是“插入”功能。

2

如果基类函数变为隐藏,编译器可能会产生警告,说明它可以生成。如果有,启用它。这将捕获常量冲突和参数列表中的差异。不幸的是,这不会发现拼写错误。

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

20

类似于C#的override关键字不是C++的一部分。

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

+2

这是如果你碰巧使用Visual C++ – 2009-02-01 16:45:25

+4

使用Visual C++不会在C++中使用`override'关键字;但这可能意味着您正在使用某些可以编译一些无效的C++源代码的东西。 ;) – 2009-02-01 16:56:41

+3

覆盖无效的事实C++意味着标准是错误的,而不是Visual C++ – Jon 2010-06-04 06:05:48

15

据我所知,难道你不能只是抽象吗?

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

我以为我在www.parashift.com上看过,你实际上可以实现一个抽象方法。对我个人来说这是有道理的,它唯一做的事情就是强制子类来实现它,没有人说它没有被允许有一个实现本身。

11

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

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

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

在MSVC++,你可以同时使用本机和CLR代码keyword override

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

override作品MSVC++。