2009-01-30 109 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++。