c++ - puras - se llamo a una funcion virtual pura mientras la aplicacion estaba ejecutandose
¿Hay algún punto en el uso de ''sobrescribir'' al anular una función virtual pura? (4)
Por ejemplo:
class Base {
virtual void my_function() = 0;
};
class Derived : Base {
void my_function() override;
};
Según lo que leí, la palabra clave de override
se usa para asegurarnos de que tenemos la firma correcta en la función que estamos anulando, y parece ser su único uso.
Sin embargo, en el caso de una función virtual pura, el compilador arrojaría un error si usamos una firma incorrecta en la clase Derivada (o clase Base, dependiendo de cómo uno vea las cosas). Entonces, ¿hay algún punto al agregar la override
al final de la declaración Derived::my_function()
?
Sin embargo, en el caso de una función virtual pura, el compilador arrojaría un error si usamos una firma incorrecta en la clase Derivada
No, esto compila:
class Base {
virtual void my_function() = 0;
};
class Derived : Base {
void my_function(int);
// ^^^ mistake!
};
Si bien esto no:
class Base {
virtual void my_function() = 0;
};
class Derived : Base {
void my_function(int) override;
};
error:
void Derived::my_function(int)
marcó laoverride
, pero no anula
El error del que se trata solo se produce al crear una instancia de Derived
- override
permite detectar el error antes y hace que la definición de Derived
sea más clara / más legible.
¡Sí!
Mejora la claridad del código : la palabra clave de override
evita la ambigüedad y transmite el significado de anular su método de clase base.
Evita el posible uso involuntario : en el futuro, si la clase base cambia la firma del método (aquí virtual
), fuerza a la clase derivada para que cambie en consecuencia. (con error de compilador). De lo contrario (sin palabras clave de override
) se podría considerar method overload
, lo cual no es intencionado.
Por lo general, no molestarse con la override
solo mueve un error. Encuentro la ubicación donde se obtiene el error mejor, en el punto donde se define el método que no se puede anular, en lugar de cuando se crea una instancia de la clase.
Pero, hay una manera de que esto proteja contra un error de tiempo de ejecución.
struct Base {
virtual void foo(int x = 0) = 0;
void foo(double d) {
foo( (int)d );
}
};
inline void Base::foo(int x) { std::cout << "Default foo(" << x << ")/n"; }
struct Derived:Base {
using Base::foo;
virtual void foo() { // oops, no int!
std::cout << "Derived::foo()/n";
Base::foo();
}
};
struct Derived2:Derived {
virtual void foo(int x=0) override {
std::cout << "Derived2::foo()/n";
Derived::foo(x);
}
};
aquí tenemos la intención de que cada foo
llame a su padre foo
. Pero debido a que Derived::foo
no anula la misma firma que Base::foo
, no se invoca.
Agregue la override
después de foo()
en Derived
y obtenemos un error de tiempo de compilación.
Y sí, implementé la función virtual pura Base::foo
.
Sí, es una buena idea usar la palabra clave override
consistentemente como una práctica defensiva.
Considere un rediseño cuando el autor de la Base
decida que my_function
ya no debería ser puramente virtual, y también que debería tomar un nuevo parámetro. Con la override
en su lugar, el compilador detectará este problema; sin una override
su clase Derived
continuaría compilando.