2017-02-04 1 views
3

Ceci est ma situation:Erreur lors de la substitution C++ fonction virtuelle

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

Maintenant, quand je l'appelle:

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

La méthode de classe de base est appelée. Je suis assez novice en ce qui concerne les règles de reliure de la méthode C++, alors pouvez-vous me dire où je me trompe? J'apprécie votre aide.

MISE À JOUR Il semble que même avec convolution Mat en ligne virtuelle ((mat Mat &, i, int j, les lignes int, int CLO) Il ne fonctionne pas.

C'est une course programme compilé avec g ++ 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; 
    } 

il imprime 1 au lieu de 2. J'ai utilisé virtuel pour assurer la liaison dynamique, mais il ne semble pas être assez, aussi avec mot-clé « prioritaire ».

+2

Pour remplacer une fonction, vous devez avoir la signature exacte de la classe de base. Puisque vous changez le type de retour, vous ne surchargez pas la fonction de classe de base. Cependant, avec le code que vous montrez, la fonction correcte doit être appelée. Est-ce copier-coller à partir de votre code * réel *? Pouvez-vous s'il vous plaît essayer de créer un [Exemple minimal, complet et vérifiable] (http://stackoverflow.com/help/mcve) et nous montrer. –

+1

En ce qui concerne votre édition, appelez-vous la fonction virtuelle sur 'f' ou' s'? Qu'est-ce que 's'? Et si c'est vraiment 'f' alors vous devriez probablement lire sur [* object slicing *] (http://stackoverflow.com/questions/274626/what-is-object-slicing). –

+0

Polymorphisme fonctionne uniquement en utilisant des pointeurs ou des références à la classe de base. Vous avez un découpage d'objet. –

Répondre

1

Lorsque vous attribuez un objet de classe dérivée à un objet de classe de base comme ça, vous ne pas atteindre l'envoi dynamique, vous obtenez slicing (tous les membres de données supplémentaires de SubFilter sont perdus)

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

lieu vous devez le passer par pointeur ou référence (sûr), comme ceci:

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

Essayé, mais il ne compile pas – diningphil

+0

'shared_ptr' et' auto' ont été introduits dans C++ 11 , aussi '#include ' pour 'shared_ptr'. Les pointeurs ou les références simples fonctionneraient de la même manière, moins le potentiel de fuite de mémoire. [Regardez ceci] (http://en.cppreference.com/w/cpp/language/virtual). – w1ck3dg0ph3r

6

Une méthode surchargée doit avoir la même signature, c'est-à-dire l'argument et les types de retour, comme méthode de base. Le compilateur peut vous avertir si ceux-ci ne correspondent pas si vous ajoutez le mot-clé à la signature pour remplacer le mot-clé.

+0

Merci, c'était une erreur vraiment stupide :) – diningphil

+1

Juste une correction mineure: les types de retour covariant sont corrects, bien que rares.Autrement dit, différents types de retour sont autorisés si la fonction dans la classe de base et la fonction dans la classe dérivée renvoient des pointeurs ou les deux renvois et le type de retour de la fonction dans la classe dérivée est un pointeur ou une référence à un type dérivé du type que le pointeur ou la référence que la fonction dans la classe de base renvoie. (Ouf, c'était épuisant!) Par exemple, 'derived * D :: f()' remplace 'la base virtuelle * B :: f()' quand 'D' est dérivé de' B' et 'derived' est dérivé de' base'. –

+0

merci, j'ai oublié ça. –

1

Il existe un mot-clé en C++ appelé override. Il résoudre exactement le problème que vous avez mentionné:

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

La présence du override assurer que la méthode remplace vraiment la méthode de classe de base.

Dans votre code, cela provoquera une erreur de compilation car la classe dérivée ne remplace pas, puisque les signatures sont différentes.

+1

Non, cela ne résoudra pas le problème, puisque les signatures des deux méthodes ne sont pas les mêmes – Soeren

+0

@Soeren J'ai clarifié la réponse. –

+0

"il va faire une compilation" - Je crois que vous voulez que ce soit "Il va provoquer une erreur de compilation" .. –