una sencillos resueltos relaciones programacion poo polimorfismo orientada objetos miembros entre ejercicios ejemplos ejemplo constructores codigo clases clase c++ inheritance c++11 gotw

c++ - sencillos - miembros de una clase en programacion orientada a objetos



Casos de uso para las clases finales. (2)

Un caso de uso inusual interesante que he encontrado que describí here . En resumen, al evitar la herencia de su clase int-like, se compra la posibilidad de reemplazarla con un tipo incorporado en las futuras versiones de su biblioteca, sin el riesgo de romper el código de su usuario.

Pero un ejemplo más común es la desvirtualización . Si marca su clase como final, el compilador puede aplicar ciertas optimizaciones en tiempo de ejecución. Por ejemplo,

struct Object { virtual void run() = 0; virtual ~Object() {} }; struct Impl final : Object { void run() override {} }; void fun(Impl & i) { i.run(); // inlined! }

La llamada a i.run() ahora puede estar en línea debido al especificador final . El compilador sabe que vtable no será necesario.

Estaba leyendo comments sobre el redux de Gurú de la Semana de Herb Sutter sobre virtual funciones virtual , y finalmente lo vi mencionando esto:

[...] "los usos de final son más raros" - bueno, en cierto modo son. No conozco muchos, y durante la estandarización, Bjarne pidió repetidamente ejemplos de problemas que resolvió y patrones en los que se debería usar, y no recuerdo ninguno de los principales que se destacaron. El único que conozco de antemano es que si está definiendo un módulo de biblioteca (que aún no es un concepto estándar), hacer que las clases de hoja sean definitivas puede dar al compilador más información para desvirtualizar las llamadas debido a que el código de fuera de la biblioteca ganó. Además, no estoy seguro de lo importante que es en estos días en presencia de la optimización del programa completo, incluida la desvirtualización agresiva.

Esa respuesta no proporciona muchos ejemplos sobre los casos de uso para las clases final , y me gustaría saber qué problemas puede resolver realmente. ¿Sabe alguna, o la final de las clases solo se convertirá en una característica poco clara y casi no utilizada?


final puede ser útil cuando proporciona una (tipo de) fachada a la interfaz inicial, que es más fácil de usar por subclases. Considerar:

class IMovable { public: void GoTo(unsigned position) = 0; } class Stepper : public IMovable { public: void GoTo(unsigned position) final; protected: virtual void MoveLeft() = 0; virtual void MoveRight() = 0; } void Stepper::GoTo(unsigned position) { for(;current_pos < position; current_pos++) { MoveRight(); } for(;current_pos > position; current_pos--) { MoveLeft(); } }

Ahora, si desea derivar de Stepper, verá que debe anular MoveRight y MoveLeft , pero no debe anular GoTo .

Es obvio en este pequeño ejemplo, pero si IMovable tenía 20 métodos y Stepper tenía 25, y existían implementaciones predeterminadas, entonces podría tener dificultades para determinar qué debería y qué no debería anular. Me he encontrado con una situación como esta en una biblioteca relacionada con hardware. Pero no llamaría a esto un problema importante que valga la pena abordar por el estándar;)