2009-12-16 10 views
7

Tuve un problema frustrante recientemente que se redujo a un error de codificación muy simple. Considere el siguiente código:Advertencia por falta de palabra clave virtual

#include <iostream> 

class Base 
{ 
public: 
    void func() { std::cout << "BASE" << std::endl; } 
}; 

class Derived : public Base 
{ 
public: 
    virtual void func() { std::cout << "DERIVED" << std::endl; } 
}; 

int main(int argc, char* argv[]) 
{ 
    Base* obj = new Derived; 
    obj->func(); 
    delete obj; 

    return 0; 
} 

La salida es

BASE

Obviamente (para este caso), que quería decir que poner la palabra clave virtual en base :: func por lo que se deriva :: func se llamaría en main. Me doy cuenta de que esto es (probablemente) permitido por el estándar de C++, y posiblemente con buenas razones, pero me parece que el 99% de las veces esto sería un error de codificación. Sin embargo, cuando compilé usando g ++ y todas las opciones de -Wblah que pude pensar, no se generaron advertencias.

¿Hay alguna manera de generar una advertencia cuando tanto una clase base como una derivada tienen funciones miembro del mismo nombre donde la función de la clase derivada es virtual y la función de la clase base no?

+0

'delete' en el ejemplo no puede destruir' 'Derived' porque base' no tiene un destructor' virtual' –

Respuesta

5

En Visual C++ puede usar la extensión override. De esta manera:

virtual void func() override { std::cout << "DERIVED" << std::endl; } 

Esto dará un error si la función no anula realmente un método de clase base. Lo uso para TODAS las funciones virtuales. Me suelen definir una macro como esta:

#ifdef _MSC_VER 
#define OVERRIDE override 
#else 
#define OVERRIDE 
#endif 

, así que puede utilizar de esta manera:

virtual void func() OVERRIDE { std::cout << "DERIVED" << std::endl; } 

he buscado algo como esto en g ++, pero no pude encontrar un concepto similar.

Lo único que no me gusta de Visual C++ es que el compilador no puede exigirlo (o al menos advertirlo) sobre todas las funciones anuladas.

+0

utilizo esto también. También es útil cuando alguien cambia la firma de una función (agregando un parámetro, etc.) pero falla al actualizar la (s) contraparte (s) base o derivada (s) derivada (s). Normalmente la virtualidad dejaría de funcionar silenciosamente, pero este truco hace que el compilador genere un error. –

+1

¡Genial! No sabía acerca de esta extensión. Probablemente usaré esto para mis propios proyectos ya que uso Visual Studio, pero para este proyecto en particular tendré que apegarme a g ++ :( – Jonesinator

+2

tenga en cuenta que 'override' está en C++ 11, entonces eso funcionará con gcc y clang recientes en modo C++ 11 ('-std = C++ 11') –

3

No conozco ninguna bandera de g ++ que produzca una advertencia al respecto (por no decir que no hay una), pero diría que es un error bastante raro. La mayoría de las personas escribe primero la clase base, como una interfaz que usa funciones virtuales puras. Si hubiera dicho:

void func() = 0; 

, entonces obtendría un error de sintaxis.

1

hombre gcc

-Woverloaded-virtual (C++ y Objective-C++ solamente) Advertir cuando una declaración de función oculta funciones virtuales de una clase base. Por ejemplo, en:

  struct A { 
      virtual void f(); 
      }; 

      struct B: public A { 
      void f(int); 
      }; 

    the "A" class version of "f" is hidden in "B", and code like: 

      B* b; 
      b->f(); 

    will fail to compile. 
+0

El uso de esta opción no avisa en el código publicado anteriormente.En este caso, Foo :: func no es virtual (que es un requisito previo de la advertencia), e incluso si lo fuera, no activaría la advertencia porque Bar :: func coincide con la firma correcta. Si configuré Foo :: func virtual Y cambié la firma de Bar :: func (es decir, func (int)) solo se activa la advertencia. En mi caso, estoy anulando una función NO virtual de Foo, lo que significa que si tengo un Foo *, se llamará a la implementación de Foo, y no a la implementación de Bar. Sin embargo, solo si tengo un Bar *, se llamará a la implementación del Bar. – Jonesinator

Cuestiones relacionadas