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 const
declaració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
override
palabra clave de C ++ 11 :fuente
override
debe 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
override
palabra clave de C # no es parte de C ++.En gcc,
-Woverloaded-virtual
advierte 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
override
una palabra clave en C ++; Sin embargo, podría significar que está utilizando algo que puede compilar código fuente C ++ no válido. ;)override
funcionalidad 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]]
override
una 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 yoverride
convertirlo 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
override
palabra 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
override
override
funciona 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
override
palabra 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
override
especificador para garantizar el polimorfismo dinámico (anulación de función).fuente