Tengo una clase base con una función virtual y quiero anular esa función en una clase derivada. ¿Hay alguna forma de hacer que el compilador verifique si la función que declaré en la clase derivada en realidad anula una función en la clase base? Me gustaría agregar alguna macro o algo que asegure que no declare accidentalmente una nueva función, en lugar de anular la anterior.
Toma este ejemplo:
class parent {
public:
virtual void handle_event(int something) const {
// boring default code
}
};
class child : public parent {
public:
virtual void handle_event(int something) {
// new exciting code
}
};
int main() {
parent *p = new child();
p->handle_event(1);
}
Aquí parent::handle_event()se llama en lugar de child::handle_event(), porque el método del niño pierde la constdeclaración y, por lo tanto, declara un nuevo método. Esto también podría ser un error tipográfico en el nombre de la función o una pequeña diferencia en los tipos de parámetros. También puede suceder fácilmente si la interfaz de la clase base cambia y en algún lugar no se actualizó alguna clase derivada para reflejar el cambio.
¿Hay alguna forma de evitar este problema? ¿Puedo decirle al compilador o alguna otra herramienta que verifique esto por mí? ¿Algún indicador de compilador útil (preferiblemente para g ++)? ¿Cómo evitas estos problemas?

Respuestas:
Desde g ++ 4.7, comprende la nueva
overridepalabra clave de C ++ 11 :fuente
overridedebe usarse en la definición. Una implementación en línea es tanto definición como implementación, así que está bien.Algo como la
overridepalabra clave de C # no es parte de C ++.En gcc,
-Woverloaded-virtualadvierte contra la ocultación de una función virtual de clase base con una función del mismo nombre pero con una firma lo suficientemente diferente como para no anularla. Sin embargo, no lo protegerá contra la falla al anular una función debido a una mala ortografía del nombre de la función.fuente
overrideuna palabra clave en C ++; Sin embargo, podría significar que está utilizando algo que puede compilar código fuente C ++ no válido. ;)overridefuncionalidad de estilo C # ; Rara vez he tenido problemas con anulaciones fallidas y han sido relativamente fáciles de diagnosticar y solucionar. Uno con lo que no estaré de acuerdo es que los usuarios de VC ++ deberían usarlo. Preferiría que C ++ se parezca a C ++ en todas las plataformas, incluso si un proyecto en particular no necesita ser portátil. Vale la pena señalar que C ++ 0x tendrá atributos y[[base_check]], por lo tanto, puede optar por anular la verificación si lo desea.[[override]][[hiding]]overrideuna palabra clave , parece que sí . Bueno, no es una palabra clave adecuada, sino un identificador especial en C ++ 11. Microsoft presionó lo suficiente para hacer un caso especial de esto y seguir el formato general de atributos yoverrideconvertirlo en el estándar :)Hasta donde yo sé, ¿no puedes simplemente hacerlo abstracto?
Pensé haber leído en www.parashift.com que en realidad se puede implementar un método abstracto. Lo que tiene sentido para mí personalmente, lo único que hace es obligar a las subclases a implementarlo, nadie dijo nada sobre que no se le permita tener una implementación en sí.
fuente
BaseClass::method()) sea llamado en la implementación derivada (digamosDerivedClass::method()), por ejemplo, para un valor predeterminado.En MSVC, puede utilizar la
overridepalabra clave CLR incluso si no está compilando para CLR.En g ++, no hay una forma directa de hacer cumplir eso en todos los casos; otras personas han dado buenas respuestas sobre cómo detectar diferencias de firma utilizando
-Woverloaded-virtual. En una versión futura, alguien podría agregar una sintaxis similar__attribute__ ((override))o equivalente usando la sintaxis C ++ 0x.fuente
En MSVC ++ puedes usar palabras clave
overrideoverridefunciona tanto para código nativo como CLR en MSVC ++.fuente
Haga que la función sea abstracta, de modo que las clases derivadas no tengan otra opción que anularla.
@Ray Tu código no es válido.
Las funciones abstractas no pueden tener cuerpos definidos en línea. Debe modificarse para convertirse
fuente
Sugeriría un ligero cambio en su lógica. Puede funcionar o no, dependiendo de lo que necesite lograr.
handle_event () todavía puede hacer el "código predeterminado aburrido", pero en lugar de ser virtual, en el punto en el que desea que haga el "nuevo código emocionante", haga que la clase base llame a un método abstracto (es decir, debe ser anulado) que será proporcionado por su clase descendiente.
EDITAR: Y si luego decide que algunas de sus clases descendientes no necesitan proporcionar un "nuevo código interesante", entonces puede cambiar el resumen a virtual y proporcionar una implementación de clase base vacía de esa funcionalidad "insertada".
fuente
Su compilador puede tener una advertencia que puede generar si una función de clase base se oculta. Si es así, habilítelo. Eso detectará conflictos constantes y diferencias en las listas de parámetros. Desafortunadamente, esto no revelará un error de ortografía.
Por ejemplo, esta es la advertencia C4263 en Microsoft Visual C ++.
fuente
La
overridepalabra clave C ++ 11 cuando se usa con la declaración de función dentro de la clase derivada, obliga al compilador a verificar que la función declarada esté anulando alguna función de la clase base. De lo contrario, el compilador arrojará un error.Por lo tanto, puede usar el
overrideespecificador para garantizar el polimorfismo dinámico (anulación de función).fuente