2009-09-04 6 views
1

Je travaille actuellement sur un projet C++ où j'ai une interface abstraite implémentée plus tard. L'interface possède également une méthode implémentée que ma mise en œuvre ne remplace pas. Mon problème est que lors de l'utilisation de mon implémentation, le compilateur (MSVC) ne voit pas la méthode d'interface. Quelles sont les causes, et comment puis-je le résoudre?méthode virtuelle non vue dans l'implémentation

Voici le code.

#include <string> 
#include <vector> 
using std::string; 

class A 
{ 
    public: 
    string name; 
}; 

class interface 
{ 
public: 
    virtual int num_foo() = 0; 
    virtual A* foo(int) = 0; 
    virtual A* foo(string &name){ 
     for (int i(0); i < num_foo(); i++) 
      if (foo(i)->name == name) 
       return foo(i); 
     return 0; 
    } 
}; 

class implementation : public interface 
{ 
public: 
    virtual int num_foo() { return m_foos.size(); } 
    virtual A* foo(int i) { 
     //check range 
     return &m_foos[i]; 
    } 
    std::vector<A> m_foos; 
}; 

int main(...) 
{ 
    implementation impl; 
    // impl is properly initialized here 

    string name("bar"); 
    // here comes my problem, the MSVC compiler doesn't see foo(string &name) 
    // and gives an error 
    A *a = impl.foo(name); 
} 
+2

J'ai collé votre code dans mon éditeur d'avoir un coup d'oeil, mais j'ai abandonné après je fixe un demi- douzaine d'erreurs et il n'a toujours pas compilé. Est-ce si difficile de fournir un code qui ne pose que le seul problème que vous posez? En l'état, je ne peux pas voir laquelle des dizaines d'erreurs dont vous vous plaignez. Fixe ton code. – sbi

+1

désolé pour le mauvais code. J'ai maintenant corrigé les erreurs et maintenant mon problème est présent. –

Répondre

5

La résolution de nom se produit avant la résolution de surcharge. Dans impl.foo(name), le compilateur regarde la classe implementation et ne trouve que virtual A& foo(int i). Il ne regarde pas la classe de base car il a trouvé une fonction avec le bon nom.

Pour corriger cette utilisation, vous pouvez ajouter une déclaration using interface::foo à la classe dérivée pour extraire toutes les versions de base de foo dans la classe dérivée à des fins de résolution de surcharge. Habituellement, je préfère éviter les fonctions surchargées et je donnerais probablement les variantes de foo noms de fonctions différentes.

(D'autres erreurs sont que vous ne définissez pas string, vector ou m_ones, vous essayez d'utiliser -> au lieu de . sur une référence et que vous essayez de revenir 0 en fonction renvoyant une référence à un A.)

+0

+1 pour une explication claire ainsi que deux solutions de contournement proposées! – RichieHindle

+0

Merci d'avoir répondu à ma question et d'avoir prévu le mauvais code fourni. –

3

pour republier les méthodes de base (tels que foo (string)) dans une sous-classe pour la surcharge, ajouter

using interface::foo; 

dans la mise en œuvre de la classe.

+0

Merci pour la réponse rapide et bonne! –

1
class implementation : public interface{ 
    public: 
     using interface::foo; 
     int num_foo() { return m_foos.size(); } 
     A& foo(int i) 
     { //check range 
      return m_ones[i]; 
     } 
     vector<A> m_foos; 
     vector<A> m_ones; 
}; 
0

Ceci est seulement un problème parce que vous accédez à l'interface implementation, qui a un membre foo, comme on l'a déjà dans la réponse par @ charles-bailey.

sémantiquement, ce que vous essayez d'appeler est le foo méthode interface, alors vous devriez probablement appeler réellement:

int main() 
{ 
    implementation impl; 
    string name("bar"); 
    interface& interf = impl; 
    A *a = interf.foo(name); 
    A *b = interf.foo(4); 
} 

Cela vous permettra également de mettre en œuvre le Non-Virtual Interface idiom, en faisant implementation::foo privé. Vous échoueriez toujours si vous essayez d'appeler directement le impl.foo, mais vous échoueriez pour tous les types d'argument, avec la même erreur.

(Je sais que cette question est vieux, mais NVI est plus ...)

Questions connexes