¿Cuál es la diferencia entre herencia pública, privada y protegida en C++?

7 minutos de lectura

Cuál es la diferencia entre public, privatey protected ¿herencia en C++?

Todas las preguntas que he encontrado en SO tratan de casos específicos.

avatar de usuario
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;
};
  • Todo lo que es consciente de Base también es consciente de que Base contiene publicMember.
  • Sólo los niños (y sus hijos) son conscientes de que Base contiene protectedMember.
  • nadie mas Base es consciente de privateMember.

Por “es consciente de”, me refiero a “reconocer la existencia de, y por lo tanto ser capaz de acceder”.

Siguiente:

Lo mismo sucede con la herencia pública, privada y protegida. Consideremos una clase Base y una clase Child que hereda de Base.

  • Si la herencia es publictodo lo que es consciente de Base y Child también es consciente de que Child hereda de Base.
  • Si la herencia es protectedsolamente Childy sus hijos, son conscientes de que heredan de Base.
  • Si la herencia es privatenadie 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

avatar de usuario
doug t

Tiene que ver con cómo se exponen los miembros públicos de la clase base desde la clase derivada.

  • público -> los miembros públicos de la clase base serán públicos (generalmente el valor predeterminado)
  • protegido -> los miembros públicos de la clase base estarán protegidos
  • privado -> los miembros públicos de la clase base serán privados

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

  1. 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

  1. 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

  1. 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

  1. Agregar

    class pair {
    public:
      First first;
      Second second;
    };
    
  2. Accesorios

    class window {
    public:
        int getWidth() const;
    };
    

protegido miembro

  1. Proporcionar acceso mejorado para clases derivadas

    class stack {
    protected:
      vector<element> c;
    };
    
    class window {
    protected:
      void registerClass(window_descriptor w);
    };
    

privado miembro

  1. 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

avatar de usuario
Zelldon

Privado:

Solo los miembros de esa clase base pueden acceder a los miembros privados de una clase base.

Público:

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.

Protegido:

Los miembros de la clase base, así como los miembros de su clase derivada, pueden acceder a los miembros protegidos de una clase base.


En breve:

privado: base

protegido: base + derivada

público: base + derivado + cualquier otro miembro

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad