2009-09-27 12 views
7

estoy frente a un problema en C++:C++ problema de anulación/sobrecarga

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

estoy usando g ++ 4.0.1 y el error de compilación:

$ 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*) 

¿Por qué debo especificar que la llamada de some_func (param1) en la clase B es A :: some_func (param1)? ¿Es un error de g ++ o un mensaje aleatorio de g ++ para evitar casos especiales que no veo?

+0

Eso es extraño. Una función de clase base protegida debe ser visible para una subclase, virtual, sobrecargada o no. –

Respuesta

11

El problema es que en la clase derivada está ocultando el método protegido en la clase base. Puedes hacer un par de cosas, ya sea que califiques por completo el método protegido en el objeto derivado o si lo pones en el alcance con una directiva 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

¿Por qué lo estoy escondiendo? Solo estoy anulando el segundo. Normalmente, g ++ debe mantener la firma del init sobrecargado en el vtable de B pero ese no es el caso. ¿Por qué no mantiene las firmas de todos los métodos? ¿Por qué pierde el sobrecargado (estoy redefiniendo uno de ellos)? – fedj

+1

Cuando define un método con un nombre en una clase derivada, ocultará todos los demás métodos con el mismo nombre en la jerarquía. Cuando el compilador descubra que está llamando 'some_func' a través de una referencia de tipo estático B, intentará hacer coincidir todas las ocurrencias de' some_func' dentro de B y no intentará escalar la jerarquía para encontrar posibles coincidencias en las clases base. –

+0

¿Es un comportamiento predeterminado de g ++ evitar tamaños grandes de tabla de acceso o es la definición de C++ y cada compilador hará el mismo error? Porque normalmente, si no era una sobrecarga en la clase A (digamos otro nombre de método), la firma se habría copiado en la clase B vtable. – fedj