2009-09-27 8 views
7

Je suis face à un problème en C++:problème override/surcharge C de

#include <iostream> 

class A 
{ 
protected: 
    void some_func(const unsigned int& param1) 
    { 
    std::cout << "A::some_func(" << param1 << ")" << std::endl; 
    } 
public: 
    virtual ~A() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    some_func(param1); 
    } 
}; 

class B : public A 
{ 
public: 
    virtual ~B() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    some_func(param1); 
    } 
}; 

int main(int, char**) 
{ 
    A* t = new B(); 
    t->some_func(21, "some char*"); 
    return 0; 
} 

J'utilise g ++ 4.0.1 et l'erreur de compilation:

$ g++ -W -Wall -Werror test.cc 
test.cc: In member function ‘virtual void B::some_func(const unsigned int&, const char*)’: 
test.cc:24: error: no matching function for call to ‘B::some_func(const unsigned int&)’ 
test.cc:22: note: candidates are: virtual void B::some_func(const unsigned int&, const char*) 

Pourquoi dois-je dois préciser que l'appel de some_func (param1) dans la classe B est A :: some_func (param1)? Est-ce un bug g ++ ou un message aléatoire de g ++ pour éviter les cas spéciaux que je ne vois pas?

+0

C'est étrange. Une fonction de classe de base protégée doit être visible pour une sous-classe, virtuelle, surchargée ou non. –

Répondre

11

Le problème est que dans la classe dérivée vous masquez la méthode protégée dans la classe de base. Vous pouvez faire quelques choses, soit vous qualifiez complètement la méthode protégée dans l'objet dérivé, soit vous mettez cette méthode dans la portée avec une directive using:

class B : public A 
{ 
protected: 
    using A::some_func; // bring A::some_func overloads into B 
public: 
    virtual ~B() {} 
    virtual void some_func(const unsigned int& param1, const char*) 
    { 
    A::some_func(param1); // or fully qualify the call 
    } 
}; 
+0

Pourquoi je le cache? Je suis juste en train de dépasser le second. Normalement, g ++ doit conserver la signature de l'init surchargé dans la vtable de B mais ce n'est pas le cas. Pourquoi ne garde-t-il pas les signatures de toutes les méthodes? Pourquoi perd-il la surcharge (je redéfinis l'un d'entre eux)? – fedj

+1

Lorsque vous définissez une méthode avec un nom dans une classe dérivée, elle masque toutes les autres méthodes ayant le même nom dans la hiérarchie. Lorsque le compilateur trouve que vous appelez 'some_func' par le biais d'une référence de type B statique, il essayera de le faire correspondre à toutes les occurrences de' some_func' dans B lui-même et n'essaiera pas d'escalader la hiérarchie pour trouver des correspondances possibles dans les classes de base. –

+0

Est-ce un comportement g ++ par défaut pour éviter les grandes tailles vtable ou est-ce la définition C++ et chaque compilateur fera la même erreur? Parce que normalement, s'il n'y avait pas de surcharge dans la classe A (disons un autre nom de méthode), la signature aurait été copiée dans la classe B vtable. – fedj