Cuál es la diferencia entre public
, private
y protected
¿herencia en C++?
Todas las preguntas que he encontrado en SO tratan de casos específicos.
Cuál es la diferencia entre public
, private
y protected
¿herencia en C++?
Todas las preguntas que he encontrado en SO tratan de casos específicos.
Anzurio
Para responder a esa pregunta, me gustaría describir los accesos de los miembros primero con mis propias palabras. Si ya sabe esto, salte al encabezado “siguiente:”.
Hay tres accesorios que conozco: public
, protected
y private
.
Dejar:
class Base {
public:
int publicMember;
protected:
int protectedMember;
private:
int privateMember;
};
Base
también es consciente de que Base
contiene publicMember
.Base
contiene protectedMember
.Base
es consciente de privateMember
.Por “es consciente de”, me refiero a “reconocer la existencia de, y por lo tanto ser capaz de acceder”.
Lo mismo sucede con la herencia pública, privada y protegida. Consideremos una clase Base
y una clase Child
que hereda de Base
.
public
todo lo que es consciente de Base
y Child
también es consciente de que Child
hereda de Base
.protected
solamente Child
y sus hijos, son conscientes de que heredan de Base
.private
nadie más que Child
es consciente de la herencia.Me gustaría agregar algunas palabras de que la visibilidad en C++ se basa en la clase en lugar del objeto, lo que significa que los objetos de la misma clase pueden acceder a los campos privados de los demás sin restricciones.
– Zhe Chen
27 de abril de 2015 a las 13:29
Si tiene dificultades para entender esto, lea la respuesta de Kirill V. Lyadvinsky, luego regrese y lea esto.
– El Vivandiere
25/06/2015 a las 22:35
Este es solo otro caso que ilustra cómo, en su mayor parte, heredar de SomeBase
es como una forma codificada de componer un miembro anónimo de tipo SomeBase
. Este, como cualquier otro miembro, tiene un especificador de acceso, que ejerce el mismo control sobre el acceso externo.
– subrayado_d
27 de febrero de 2016 a las 18:28
@ZheChen si tengo objetos Tom y Jerry de la clase Persona con edad de campo privado, ¿cómo accede (¿y modifica?) la edad de Jerry usando Tom?
– generación
12/07/2016 a las 20:25
¿Podría ilustrar lo que quiere decir con “consciente de la ‘herencia'”? Puedo entender “puedo acceder a esto, no puedo acceder a aquello”, pero no lo entiendo cuando uno dice “Sé que A hereda de B”. ¿Qué estoy haciendo aquí? ¿Estoy comprobando la herencia?
– lineil
10 sep 2018 a las 22:44
El primero en mencionar la falta de un modificador (como en Clase: SuperClass) produce privado. Esta es una pieza importante que los demás se están perdiendo, junto con explicaciones detalladas. +1
– Agua
25/10/2016 a las 16:22
Overkill IMO, pero me gusta la mesa al principio.
– cp.engr
3 de agosto de 2018 a las 21:43
doug t
Tiene que ver con cómo se exponen los miembros públicos de la clase base desde la clase derivada.
Como señala litb, la herencia pública es la herencia tradicional que verá en la mayoría de los lenguajes de programación. Es decir, modela una relación “ES-A”. La herencia privada, algo AFAIK peculiar de C ++, es una relación “IMPLEMENTADA EN TÉRMINOS DE”. Eso es lo que quieres usar 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 una base privada, convertirla en un miembro derivado para reutilizar la funcionalidad de la clase base.
Mejor decir “público: la herencia la verá todo el mundo”. protected: la herencia solo la verán las clases derivadas y los amigos”, “private: la herencia solo la verán la clase misma y los amigos”. Esto es diferente de su redacción, ya que no solo los miembros pueden ser invisibles, sino también la relación IS-A puede ser invisible.
– Johannes Schaub – litb
13 mayo 2009 a las 20:59
La única vez que usé la herencia privada fue para hacer exactamente lo que describe Doug T, es decir, “quieres usar la interfaz pública en la clase derivada, pero no quieres que el usuario de la clase derivada tenga acceso a esa interfaz”. Básicamente lo usé para sellar la interfaz anterior y exponer otra a través de la clase derivada.
– Rico
22 de abril de 2010 a las 22:06
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 la derivada a la base no funcionarán, y static_cast
de la base a la derivada 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.
público herencia
ES-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.
class button : public window { };
protegido herencia
Protegido implementado-en-términos-de. Raramente útil. Utilizado en 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 una plantilla para seguir en el punto):
struct empty_pair_impl : protected empty_class_1
{ non_empty_class_2 second; };
struct pair : private empty_pair_impl {
non_empty_class_2 &second() {
return this->second;
}
empty_class_1 &first() {
return *this; // notice we return *this!
}
};
privado herencia
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 la clase base vacía). A menudo contención es la mejor solución, sin embargo. El tamaño de las cadenas es crítico, por lo que es un uso frecuente aquí.
template<typename StorageModel>
struct string : private StorageModel {
public:
void realloc() {
// uses inherited function
StorageModel::realloc();
}
};
público miembro
Agregar
class pair {
public:
First first;
Second second;
};
Accesorios
class window {
public:
int getWidth() const;
};
protegido miembro
Proporcionar acceso mejorado para clases derivadas
class stack {
protected:
vector<element> c;
};
class window {
protected:
void registerClass(window_descriptor w);
};
privado miembro
Mantener detalles de implementación
class window {
private:
int width;
};
Tenga en cuenta que las conversiones de estilo C permiten deliberadamente convertir una clase derivada en una clase base protegida o privada de una manera definida y segura y también 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.
Mejor decir “público: la herencia la verá todo el mundo”. protected: la herencia solo la verán las clases derivadas y los amigos”, “private: la herencia solo la verán la clase misma y los amigos”. Esto es diferente de su redacción, ya que no solo los miembros pueden ser invisibles, sino también la relación IS-A puede ser invisible.
– Johannes Schaub – litb
13 mayo 2009 a las 20:59
La única vez que usé la herencia privada fue para hacer exactamente lo que describe Doug T, es decir, “quieres usar la interfaz pública en la clase derivada, pero no quieres que el usuario de la clase derivada tenga acceso a esa interfaz”. Básicamente lo usé para sellar la interfaz anterior y exponer otra a través de la clase derivada.
– Rico
22 de abril de 2010 a las 22:06
Zelldon
Solo los miembros de esa clase base pueden acceder a los miembros privados de una clase base.
Los miembros públicos de una clase base pueden acceder a los miembros de esa clase base, los miembros de su clase derivada y los miembros que están fuera de la clase base y la clase derivada.
Los miembros de la clase base, así como los miembros de su clase derivada, pueden acceder a los miembros protegidos de una clase base.
privado: base
protegido: base + derivada
público: base + derivado + cualquier otro miembro