2017-02-04 63 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

”它会编译一个“ - 我相信你希望它是”它会导致编译错误“.. –