2017-02-04 86 views
3

這是我的情況:錯誤時,重載C++虛函數

class Filter3by3 { 
public: 
    virtual inline Mat convolution((Mat & mat, int i, int j, int rows, int cols) { 
code 

    } 
}; 

class MySobel: public Filter3by3 { 
public: 
    inline Vec3b convolution(Mat & mat, int i, int j, int rows, int cols) { 
    code 
    } 
}; 

現在,當我打電話:

Filter3by3 f = choose_filter(filtername); // Returns a Sobel filter 
Mat mat; 
s.convolution(args); 

基類方法被調用。 我很新手在C++方法綁定規則,所以你可以告訴我我錯在哪裏? 我感謝您的幫助。

UPDATE 看來,即使 虛擬串列式墊卷積((墊&墊,INT I,詮釋J,詮釋行,詮釋的cols) 它不工作。

這是一個運行程序,編譯克++ -std = C++ 11

#include <iostream> 

using namespace std; 

class Filter { 
public: 
    Filter() { } 
    virtual int ehi() { 
    cout << "1" << endl; 
    return 1; 
    } 

}; 

class SubFilter : public Filter { 
public: 
    SubFilter() : Filter() { } 

    int ehi() { 
    cout << "2" << endl; 
    return 2; 
    } 

}; 

    Filter choose_filter(){ 
    SubFilter f; 
    return f; 
    } 

    int main(int argc, char* argv[]) { 

    Filter f = choose_filter(); 
    f.ehi(); 
    return 0; 
    } 

它打印1而不是2,我使用的虛擬確保動態結合,但是它似乎沒有足夠,也與「覆蓋」關鍵字。

+2

要覆蓋某個函數,它需要具有基類的確切簽名。由於您更改了返回類型,因此您不會覆蓋基類功能。然而,用你顯示的代碼應該調用正確的函數。是來自* actual *代碼的複製粘貼嗎?你可以請嘗試創建一個[最小,完整和可驗證示例](http://stackoverflow.com/help/mcve)並向我們展示。 –

+1

關於你的編輯,你是在'f'還是's'上調用虛函數?什麼是's'?如果它真的是'f',那麼你應該閱讀[* object slicing *](http://stackoverflow.com/questions/274626/what-is-object-slicing)。 –

+0

多態僅適用於使用指針或對基類的引用。你有對象切片。 –

回答

1

當你將派生類對象的基類這樣的對象,你不實現動態調度,你實現slicing(所有的SubFilter附加數據成員的丟失)

Filter choose_filter(){ 
    SubFilter f; 
    return f; 
    } 

相反您應該通過(安全)指針或引用來傳遞它,如下所示:

std::shared_ptr<Filter> choose_filter(){ 
    return std::make_shared<SubFilter>(); 
    } 

    int main(int argc, char* argv[]) { 

    auto f = choose_filter(); 
    f->ehi(); 
    return 0; 
    } 
+0

試過了,但它不能編譯 – diningphil

+0

''shared_ptr'和'auto'是在C++ 11中引入的''shared_ptr'也包含'#include '。普通指針或引用可以起到相同的作用,減少內存泄漏的可能性。 [檢查出來](http://en.cppreference.com/w/cpp/language/virtual)。 – w1ck3dg0ph3r

6

重寫的方法必須具有與基本方法相同的簽名,即參數和返回類型。如果您將覆蓋關鍵字添加到簽名,編譯器可以通知您這些不匹配。

+0

謝謝,這是一個非常愚蠢的錯誤:) – diningphil

+1

只是一個小修正:協變返回類型是好的,雖然很少見。也就是說,如果基類中的函數和派生類中的函數都返回指針或同時返回引用,並且派生類中的函數的返回類型是指向類型的指針或引用,則允許不同的返回類型派生自基類中的函數返回的指針或引用的類型。 (Phew;那真是太累了!)例如,當'D'從'B'派生而'derived'派生自''B''時,'derived * D :: f()'覆蓋'virtual base * B :: f() base'。 –

+0

謝謝,我忘了。 –

1

C++中有一個關鍵字叫做override。這正是解決你提到的問題:

struct MySobe l: Filter3by3 { 
    inline Vec3b convolution(Mat & mat, int i, int j, int rows, int cols) override { code } 
}; 

override的存在確保該方法確實重寫了基類的方法。

在你的代碼中,它會導致編譯錯誤,因爲派生類不會覆蓋,因爲簽名是不同的。

+1

不,它不會解決問題,因爲兩種方法的簽名都不相同 – Soeren

+0

@Soeren我澄清了答案。 「 –

+0

」它會編譯一個「 - 我相信你希望它是」它會導致編譯錯誤「.. –