que - polimorfismo c++
C++ efectivo: ¿desalentar la herencia protegida? (5)
Algunos escenarios donde querrías estar protegido:
Tiene una clase base con métodos en los que sabe que nunca desea exponer la funcionalidad externa, pero sabe que será útil para cualquier clase derivada.
Tiene una clase base con miembros que deberían ser utilizados de forma lógica por cualquier clase que amplíe esa clase, pero que nunca deben exponerse fuera.
Gracias a la herencia múltiple, puede jugar con el tipo de herencia de las clases base y construir una clase más diversificada con la lógica y la implementación existentes.
Un ejemplo más concreto:
Podría crear algunas clases abstractas que sigan la lógica del patrón de diseño, digamos que tiene:
Observer
Subject
Factory
Ahora quieres que todo esto sea público, porque en general, podrías usar el patrón en cualquier cosa.
Pero, con la herencia protegida, puede crear una clase que sea un observador y un sujeto, pero solo una fábrica protegida, por lo que la parte de fábrica solo se usa en las clases heredadas. (Solo escoge patrones al azar para el ejemplo)
Otro ejemplo:
Digamos, por ejemplo, que quiere heredar de una clase de biblioteca (no es que yo lo aliente). Digamos que quieres hacer tu propia extensión de std::list<>
o una "mejor" shared_ptr
.
Podría derivar de forma protegida de la clase base (que está diseñada para tener métodos públicos).
Esto le dará la opción de usar sus propios métodos personalizados, usar la lógica de la clase y pasar la lógica a cualquier clase derivada.
Probablemente podrías usar la encapsulación en su lugar, pero la herencia sigue la lógica apropiada de IS A (o en este caso es una especie de A)
Estaba leyendo Effective C ++ de Scott Meyers (tercera edición), y en un párrafo en el Artículo 32: Asegúrese de que la herencia pública sea "is-a" en la página 151 hace el comentario (que he puesto en negrita):
Esto es cierto sólo para la herencia pública . C ++ se comportará como lo he descrito solo si Student se deriva públicamente de Person. La herencia privada significa algo completamente diferente (ver Artículo 39), y la herencia protegida es algo cuyo significado se me escapa hasta el día de hoy.
La pregunta : ¿Cómo debo interpretar este comentario? ¿Está Meyers tratando de transmitir que la herencia protegida rara vez se considera útil y debe evitarse?
(He leído la pregunta La diferencia entre la herencia privada, pública y protegida , así como la sección de herencia privada y protegida de C ++ FAQ Lite , que explican qué significa la herencia protegida, pero no me han dado mucha información sobre cuándo o por qué sería útil.)
No está desalentando exactamente la herencia protegida, solo dice que no ha encontrado ningún buen uso para ella. Tampoco he visto a nadie en ningún otro lado.
Si encuentra un par de casos de uso realmente útiles, también podría tener material para escribir un libro. :-)
No sé si Meyers nos recomienda abstenernos de utilizar la herencia protegida, pero parece que deberías evitarlo si Meyers está en tu equipo, porque al menos no podrá entender tu código.
A menos que sus compañeros de trabajo conozcan a C ++ mejor que él, es probable que usted también deba mantenerse alejado de la herencia protegida. Todos entenderán la alternativa, es decir, usar la composición.
Sin embargo, puedo imaginar un caso en el que podría tener sentido: necesita acceder a un miembro protegido en una clase cuyo código no puede cambiar pero no desea exponer una relación IS-A.
class A {
protected:
void f(); // <- I want to use this from B!
};
class B : protected A {
private:
void g() { f(); }
};
Incluso en ese caso, todavía consideraría hacer una envoltura con herencia pública que exponga a los miembros de base protegidos con métodos públicos, y luego componer con estas envolturas.
/*! Careful: exposes A::f, which wasn''t meant to be public by its authors */
class AWithF: public A {
public:
void f() { A::f(); }
};
class B {
private:
AWithF m_a;
void g() { m_a.f(); }
};
Sí, no hay muchos usos para la herencia protegida o privada. Si alguna vez piensa en la herencia privada, es probable que la composición sea más adecuada para usted. (Herencia significa ''es-a'' y composición significa ''tiene-a''.)
Mi conjetura es que el comité de C ++ simplemente agregó esto porque era muy fácil de hacer y ellos pensaron, "diablos, tal vez alguien encuentre un buen uso para esto". No es una mala característica, no hace ningún daño, solo que nadie ha encontrado un uso real para ella todavía. :PAG
Si y no. Yo mismo creo que la herencia protegida es también una mala característica. Básicamente importa todos los miembros públicos y protegidos de la clase base como miembros protegidos.
Normalmente evito a los miembros protegidos, pero son útiles en los niveles más bajos que requieren una eficiencia extrema con un compilador con mala optimización de tiempo de enlace. Pero todo lo que se basa en eso no debería estar jugando con los miembros (datos) de la clase base original y, en su lugar, debe usar la interfaz.
Lo que creo que Scott Meyer está tratando de decir es que aún puedes usar la herencia protegida si resuelve un problema, pero asegúrate de usar comentarios para describir la herencia porque no está claro semánticamente.