¿Cuál es la diferencia entre
public
,private
yprotected
herencia en C ++?
Todas las preguntas que he encontrado en SO tratan casos específicos.
c++
inheritance
encapsulation
access-specifier
c++-faq
Arsen Khachaturyan
fuente
fuente
SomeBase
es como una forma codificada de componer un miembro anónimo de tipoSomeBase
. Esto, como cualquier otro miembro, tiene un especificador de acceso, que ejerce el mismo control sobre el acceso externo.NOTA IMPORTANTE: todas las clases B, C y D contienen las variables x, y y z. Es solo cuestión de acceso.
Sobre el uso de herencia protegida y privada puede leer aquí .
fuente
Limitar la visibilidad de la herencia hará que el código no pueda ver que alguna clase hereda otra clase: las conversiones implícitas de lo derivado a la base no funcionarán, y
static_cast
de la base a lo derivado tampoco funcionará.Solo los miembros / amigos de una clase pueden ver la herencia privada, y solo los miembros / amigos y las clases derivadas pueden ver la herencia protegida.
herencia pública
IS-A herencia. Un botón es una ventana, y en cualquier lugar donde se necesite una ventana, también se puede pasar un botón.
herencia protegida
Protegido implementado en términos de. Raramente útil. Se usa
boost::compressed_pair
para derivar de clases vacías y ahorrar memoria usando la optimización de clase base vacía (el ejemplo a continuación no usa la plantilla para mantenerse en el punto):herencia privada
Implementado en términos de. El uso de la clase base es solo para implementar la clase derivada. Útil con rasgos y si el tamaño importa (los rasgos vacíos que solo contienen funciones harán uso de la optimización de clase base vacía). Sin embargo, a menudo la contención es la mejor solución. El tamaño de las cadenas es crítico, por lo que es un uso frecuente aquí
miembro público
Agregar
Accesorios
miembro protegido
Proporcionar acceso mejorado para clases derivadas
miembro privado
Mantener detalles de implementación
Tenga en cuenta que los lanzamientos de estilo C permiten a propósito lanzar una clase derivada a una clase base protegida o privada de una manera definida y segura y también lanzar en la otra dirección. Esto debe evitarse a toda costa, ya que puede hacer que el código dependa de los detalles de implementación, pero si es necesario, puede utilizar esta técnica.
fuente
Estas tres palabras clave también se utilizan en un contexto completamente diferente para especificar el modelo de herencia de visibilidad .
Esta tabla reúne todas las combinaciones posibles de la declaración de componentes y el modelo de herencia que presenta el acceso resultante a los componentes cuando la subclase está completamente definida.
La tabla anterior se interpreta de la siguiente manera (eche un vistazo a la primera fila):
Un ejemplo:
El acceso resultante para las variables
p
,q
,r
en la clase subsub es ninguno .El acceso resultante para las variables
y
,z
en la clase Sub, está protegido y para la variablex
es ninguno .Ahora definamos una subclase:
La clase definida llamada Sub, que es una subclase de la clase llamada
Super
o esaSub
clase se deriva de laSuper
clase. LaSub
clase no introduce nuevas variables ni nuevas funciones. ¿Significa que algún objeto de laSub
clase hereda todos los rasgos después de que laSuper
clase sea, de hecho, una copia deSuper
los objetos de una clase?No se . No lo hace.
Si se compila el código siguiente, obtendremos nada más que errores de compilación diciendo que
put
yget
métodos son inaccesibles. ¿Por qué?Cuando omitimos el especificador de visibilidad, el compilador supone que vamos a aplicar la denominada herencia privada . Esto significa que todos los públicos componentes superclase se convierten en privado de acceso, los componentes de la superclase privadas no serán accesibles a todos. En consecuencia, significa que no puede usar este último dentro de la subclase.
Tenemos que informar al compilador que queremos preservar la política de acceso utilizada anteriormente.
Los objetos de la
Sub
clase pueden hacer "casi" las mismas cosas que sus hermanos mayores creados a partir de laSuper
clase. "Casi" porque el hecho de ser una subclase también significa que la clase perdió acceso a los componentes privados de la superclase . No podemos escribir una función miembro de laSub
clase que pueda manipular directamente la variable de almacenamiento.Esta es una restricción muy seria. ¿Hay algún trabajo alrededor?
Sí .
El tercer nivel de acceso se llama protegido . La palabra clave protegida significa que el componente marcado con él se comporta como uno público cuando lo utiliza cualquiera de las subclases y parece privado para el resto del mundo . - Esto es cierto solo para las clases heredadas públicamente (como la clase Super en nuestro ejemplo) -
Como puede ver en el código de ejemplo, tenemos una nueva funcionalidad para la
Sub
clase y hace una cosa importante: accede a la variable de almacenamiento desde la clase Super .No sería posible si la variable se declarara como privada. En el ámbito de la función principal, la variable permanece oculta de todos modos, así que si escribe algo como:
El compilador le informará que es un
error: 'int Super::storage' is protected
.Finalmente, el último programa producirá el siguiente resultado:
fuente
Tiene que ver con cómo los miembros públicos de la clase base están expuestos de la clase derivada.
Como señala Litb, la herencia pública es una herencia tradicional que verá en la mayoría de los lenguajes de programación. Es decir, modela una relación "IS-A". La herencia privada, algo AFAIK peculiar de C ++, es una relación "IMPLEMENTADA EN TÉRMINOS DE". Es decir, desea utilizar la interfaz pública en la clase derivada, pero no desea que el usuario de la clase derivada tenga acceso a esa interfaz. Muchos argumentan que, en este caso, debe agregar la clase base, es decir, en lugar de tener la clase base como base privada, hacer un miembro derivado para reutilizar la funcionalidad de la clase base.
fuente
Tipo de herencia : Objeto heredado como :
fuente
1) Herencia pública :
a. Los miembros privados de la clase Base no son accesibles en la clase Derivada.
si. Los miembros protegidos de la clase Base permanecen protegidos en la clase Derivada.
C. Los miembros públicos de la clase Base siguen siendo públicos en la clase Derivada.
Por lo tanto, otras clases pueden usar miembros públicos de la clase Base a través del objeto de clase Derivado.
2) Herencia protegida :
a. Los miembros privados de la clase Base no son accesibles en la clase Derivada.
si. Los miembros protegidos de la clase Base permanecen protegidos en la clase Derivada.
C. Los miembros públicos de la clase Base también se convierten en miembros protegidos de la clase Derivada.
Por lo tanto, otras clases no pueden usar miembros públicos de la clase Base a través del objeto de clase Derivado; pero están disponibles para la subclase de Derivado.
3) Herencia privada :
a. Los miembros privados de la clase Base no son accesibles en la clase Derivada.
si. Los miembros protegidos y públicos de la clase Base se convierten en miembros privados de la clase Derivada.
Por lo tanto, ningún miembro de la clase Base puede acceder a otras clases a través del objeto de clase Derivado, ya que son privadas en la clase Derivada. Entonces, incluso la subclase de la clase Derivada no puede acceder a ellos.
fuente
La herencia pública modela una relación IS-A. Con
todo
D
es unB
.La herencia privada modela una relación de USO IMPLEMENTADO (o como se llame). Con
a no
D
es a , pero cada usa su en su implementación. La herencia privada siempre se puede eliminar utilizando la contención en su lugar:B
D
B
Esto
D
también se puede implementar usandoB
, en este caso usando sub_
. La contención es un acoplamiento menos estrecho entre los tipos que la herencia, por lo que en general debería preferirse. A veces, usar la contención en lugar de la herencia privada no es tan conveniente como la herencia privada. A menudo es una excusa poco convincente para ser flojo.No creo que nadie sepa qué
protected
modelos de herencia. Al menos aún no he visto ninguna explicación convincente.fuente
D
deriva de forma privadaD
, puede anular las funciones virtuales deB
. (Si, por ejemplo,B
es una interfaz de observador, entoncesD
podría implementarla y pasarthis
a funciones que requieren auch una interfaz, sin que todos puedan usarlaD
como observador). Además,D
podría hacer que los miembrosB
estén disponibles selectivamente en su interfaz haciendousing B::member
. Ambos son sintácticamente inconvenientes de implementar cuandoB
es miembro.protected
herencia que he encontrado útil con unavirtual
clase base yprotected
ctor:struct CommonStuff { CommonStuff(Stuff*) {/* assert !=0 */ } }; struct HandlerMixin1 : protected virtual CommonStuff { protected: HandlerMixin1() : CommonStuff(nullptr) {} /*...*/ }; struct Handler : HandlerMixin1, ... { Handler(Stuff& stuff) : CommonStuff(&stuff) {} };
Si hereda públicamente de otra clase, todos saben que está heredando y cualquiera puede usarlo polimórficamente a través de un puntero de clase base.
Si hereda de forma protegida, solo sus clases de niños podrán usarlo polimórficamente.
Si hereda en privado, solo usted podrá ejecutar métodos de clase principal.
Lo que básicamente simboliza el conocimiento que el resto de las clases tienen sobre su relación con la clase de sus padres.
fuente
Los miembros de datos protegidos pueden acceder a cualquier clase que herede de su clase. Los miembros de datos privados, sin embargo, no pueden. Digamos que tenemos lo siguiente:
Desde su extensión a esta clase, las referencias
this.myPrivateMember
no funcionarán. Sin embargo, lothis.myProtectedMember
hará. El valor todavía está encapsulado, por lo que si tenemos una instanciación de esta clase llamadamyObj
, entoncesmyObj.myProtectedMember
no funcionará, por lo que es similar en función a un miembro de datos privado.fuente
Basado en este ejemplo para Java ... creo que una pequeña mesa vale más que mil palabras :)
fuente
Resumen:
Al heredar, puede (en algunos idiomas) cambiar el tipo de protección de un miembro de datos en cierta dirección, por ejemplo, de protegido a público.
fuente
Privado:
A los miembros privados de una clase base solo pueden acceder miembros de esa clase base.
Público:
Los miembros públicos de una clase base pueden ser accedidos por miembros de esa clase base, miembros de su clase derivada, así como los miembros que están fuera de la clase base y la clase derivada.
Protegido:
Los miembros protegidos de una clase base pueden ser accedidos por los miembros de la clase base, así como por los miembros de su clase derivada.
En breve:
privado : base
protegido : base + derivado
public : base + derivado + cualquier otro miembro
fuente
Encontré una respuesta fácil y pensé en publicarla también para mi futura referencia.
Es de los enlaces http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/
fuente
Es esencialmente la protección de acceso de los miembros públicos y protegidos de la clase base en la clase derivada. Con la herencia pública, la clase derivada puede ver miembros públicos y protegidos de la base. Con herencia privada, no puede. Con protegido, la clase derivada y cualquier clase derivada de eso pueden verlos.
fuente