2012-04-03 18 views
16

El siguiente código de C++ creo que es correcto, pero produce algunas advertencias cuando se compila con "-Woverloaded-virtual", ¿es una advertencia falsa o hay un problema real con este código?gcc Advertencias de Woverloaded-virtual

Si esto es una advertencia falsa, ¿qué puedo hacer para evitarlo, defina todas las variantes virtuales de excepción en rids Get derivados de la advertencia, pero tal vez es una mejor solución

G ++ comando:

g++ -c -Woverloaded-virtual test.cpp 
test.cpp:22:18: warning: ‘virtual void intermediate::exception(const char*)’ was hidden [-Woverloaded-virtual] 
test.cpp:32:18: warning: by ‘virtual void derived::exception()’ [-Woverloaded-virtual] 

código C++

using namespace std; 

class base 
{ 
public: 

    virtual void exception() = 0; 
    virtual void exception(const char*) = 0; 
}; 

class intermediate : public base 
{ 
public: 

    virtual void exception() 
    { 
    cerr << "unknown exception" << endl; 
    } 

    virtual void exception(const char* msg) 
    { 
    cerr << "exception: " << msg << endl; 
    } 
}; 

class derived : public intermediate 
{ 
public: 

    virtual void exception() 
    { 
     intermediate::exception("derived:unknown exception"); 
    } 
}; 

Respuesta

18

La advertencia significa que:
Cuando no se está utilizando envío dinámico entonces su derived objeto de clase sólo puede llamar,

void exception()  

y se ocultará todos los mismos métodos con nombre de la clase intermediate Base.

Para que su objeto de clase derivado pueda invocar todos los mismos métodos nombrados en la clase base intermediate, debe agregar la siguiente línea a su clase derived.

using intermediate::exception; 

Por supuesto, usted está en la mejor posición para decidir si esto es un problema o no.

+0

¿Cómo suprimimos esta advertencia si es intencional? – Sampath

+0

No estoy seguro, pero supongo que 'void exception (const char * msg) = delete;' funcionaría. EDITAR: No, eliminar una sobrecarga como esa es un error. Pero me sorprendería si esto fuera realmente intencional, en un código bien diseñado; debería poder tratar una instancia de una clase derivada como una instancia de la clase base. –

+0

Como lo señala la otra respuesta, puede redefinirlo como 'privado 'bien. –

13

La advertencia se debe al hecho de que no se puede llamar derived::exception(const char*) en un objeto de tipo derived (oa través de un puntero a derived), a pesar de que la clase padre lo define y es virtual (por lo que se puede esperar que sea disponible en derived). Para eliminar la advertencia, lo que necesita para exponer que la función miembro en derived:

class derived : public intermediate 
{ 
public: 
    virtual void exception(const char* msg) {intermediate::exception(msg);} 
    virtual void exception() 
    { 
    intermediate::exception("derived:unknown exception"); 
    } 
}; 

O si no quiere exponer a los demás, declarará como privada sin Defintion.

class derived : public intermediate 
{ 
public: 
    virtual void exception() 
    { 
    intermediate::exception("derived:unknown exception"); 
    } 
private: 
    void exception(const char* tmp); 
}; 

ACTUALIZACIÓN: Después de doble control (y como se ha señalado por ALS) la directiva using, usted podría hacer esto también:

class derived : public intermediate 
{ 
public: 
    using intermediate::exception; // imports both declarations from intermediate 
    virtual void exception() // will not clash with the imported declaration of the 
          // same signature, but properly overriders the parent 
          // class's defition 
    { 
    intermediate::exception("derived:unknown exception"); 
    } 
}; 
+0

Para exponer la función de clase Base en la clase derivada, todo lo que OP necesita hacer es agregar 'using intermediate :: exception;'. –

+0

I [No lo creo] (http: // ideone.com/deM6L) –

+0

En realidad, no :) Pensé en escribir usando en mi publicación original, pero decidí no hacerlo (por la misma razón que escribí después de tu primer comentario, que luego eliminé, porque pensé que entraría en conflicto)) Después de tu comentario (y de escribir el mío por instinto), lo comprobé dos veces para asegurarme. Después de encontrar que tenía razón, actualicé mi respuesta, después de lo cual noté su segundo comentario con el enlace. Por supuesto, tendrás que tomar mi Ford para ello ... Pero lo actualizaré de nuevo, para que nadie tenga resentimiento :) – Attila

0

favor redefinir la función:

virtual void exception(const char* msg); en clase "derivado".

Ahora su código se compilará sin ninguna advertencia.

+0

Se compilará sin advertencias, pero ahora ha creado problemas de ODR si alguien intenta llamar eso. Probablemente se manifestarán como errores del enlazador, que generalmente son más difíciles de leer y comprender que las advertencias del compilador o los errores del compilador. –

Cuestiones relacionadas