Pregunta

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.

¿Fue útil?

Solución

Para responder a esa pregunta, primero me gustaría describir los accesos de los miembros con mis propias palabras.Si ya lo sabe, pase al título "siguiente:".

Hay tres descriptores de acceso 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 que Base es consciente de privateMember.

Por "es consciente de", me refiero a "reconocer la existencia de, y así poder acceder".

próximo:

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

  • Si la herencia es public, todo lo que es consciente de Base y Child también es consciente de que Child hereda de Base.
  • Si la herencia es protected, solo Child, y sus hijos, son conscientes de que heredan de Base.
  • Si la herencia es private, nadie más que Child es consciente de la herencia.

Otros consejos

class A 
{
public:
    int x;
protected:
    int y;
private:
    int z;
};

class B : public A
{
    // x is public
    // y is protected
    // z is not accessible from B
};

class C : protected A
{
    // x is protected
    // y is protected
    // z is not accessible from C
};

class D : private A    // 'private' is default for classes
{
    // x is private
    // y is private
    // z is not accessible from D
};

NOTA IMPORTANTE: Clases B, C y D todos contienen las variables x, y y z. Es sólo cuestión de acceso.

Sobre el uso de la herencia protegida y privada que se podía leer aquí .

La limitación de la visibilidad de la herencia será hacer que el código no es capaz de ver que algunos clase hereda de otra clase: Las conversiones implícitas de la derivada de la base no va a funcionar, y static_cast desde la base hasta la derivada tampoco funcionará .

Solamente los usuarios / amigos de una clase pueden ver la herencia privada, y sólo los miembros / amigos y las clases derivadas pueden ver la herencia protegida.

público herencia

  1. IS-A herencia. Un botón es-una ventana, y en cualquier lugar donde se necesite una ventana, un botón se puede pasar también.

    class button : public window { };
    

protegido herencia

  1. Protegida implementada en términos de. Rara vez son útiles. Se utiliza en boost::compressed_pair derivar de clases vacías y guardar memoria mediante la optimización de la clase base vacía (ejemplo de abajo no utiliza la plantilla para seguir siendo 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-in-términos-de. El uso de la clase base es sólo para la implementación de la clase derivada. Útiles con rasgos y si el tamaño importa (rasgos vacíos que sólo contienen funciones hará uso de la optimización de la clase base vacío). A menudo contención es la mejor solución, sin embargo. El tamaño de las cadenas es crítica, por lo que es un uso a menudo se ve aquí

    template<typename StorageModel>
    struct string : private StorageModel {
    public:
      void realloc() {
        // uses inherited function
        StorageModel::realloc();
      }
    };
    

público miembro

  1. Agregada

    class pair {
    public:
      First first;
      Second second;
    };
    
  2. Los descriptores de acceso

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

protegido miembro

  1. Proporcionar un mejor acceso para las 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 C-estilo yesos propósito permite la fundición una clase derivada de una clase base protegida o privada de una manera definida y segura y de echar en la otra dirección también. Esto debe evitarse a toda costa, ya que puede hacer depende de los detalles de implementación de código - pero si es necesario, se puede hacer uso de esta técnica.

Tiene que ver con cómo los miembros públicos de la clase base están expuestos a la clase derivada.

       
  • pública - miembros públicos> de la clase base serán públicas (por lo general el valor por defecto)    
  • protegida -> miembros públicos de la clase base será protegida    
  • privada - miembros públicos> de la clase base será privada

Como litb señala, la herencia pública es la herencia tradicional que se verá en la mayoría de los lenguajes de programación. Es decir que modela una relación "es-un". herencia privada, algo que yo sepa peculiar de C ++, es un "implementadas en términos de" relación. Es decir que desea utilizar de la interfaz pública en la clase derivada, pero no quieren que el usuario de la clase derivada de tener acceso a esa interfaz. Muchos sostienen que en este caso se debe agregar la clase base, que es en lugar de tener la clase de base como una base privada, que en un miembro de derivados con el fin de volver a utilizar la funcionalidad de la clase base.

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 presentando el acceso resultante a los componentes cuando la subclase está completamente definida.

enter image description here

La tabla anterior se interpreta de la siguiente manera (eche un vistazo a la primera fila):

si un componente es declarado como público y su clase es heredado como público la resultante acceso es público.

Un ejemplo:

 class Super {
    public:      int p;
    private:     int q;
    protected:   int r;
 };

 class Sub : private Super {};

 class Subsub : public Sub {};

El acceso resultante para las variables. p, q, r en la clase subsub es ninguno.

Otro ejemplo:

class Super {
    private:     int x;
    protected:   int y;
    public:      int z;
 };
class Sub : protected Super {};

El acceso resultante para las variables. y, z en la clase Sub es protegido y para variables x es ninguno.

Un ejemplo más detallado:

class Super {
private:
    int storage;
public:
    void put(int val) { storage = val;  }
    int  get(void)    { return storage; }
};
int main(void) {
    Super object;

    object.put(100);
    object.put(object.get());
    cout << object.get() << endl;
    return 0;
}

Ahora definamos una subclase:

class Sub : Super { };

int main(void) {
    Sub object;

    object.put(100);
    object.put(object.get());
    cout << object.get() << endl;
    return 0;
}

La clase definida denominada Sub, que es una subclase de la clase denominada Super o eso Sub clase se deriva de la Super clase.El Sub La clase no introduce nuevas variables ni nuevas funciones.¿Significa que cualquier objeto del Sub La clase hereda todos los rasgos después del Super clase siendo de hecho una copia de un Super objetos de clase?

No.No es así.

Si compilamos el siguiente código, no obtendremos nada más que errores de compilación que dicen que put y get Los métodos son inaccesibles.¿Por qué?

Cuando omitimos el especificador de visibilidad, el compilador asume que vamos a aplicar el llamado herencia privada.Significa que todos público Los componentes de superclase se convierten en privado acceso, los componentes privados de la superclase no serán accesibles en absoluto.En consecuencia, significa que no se le permite utilizar este último dentro de la subclase.

Tenemos que informar al compilador que queremos preservar la política de acceso utilizada anteriormente.

class Sub : public Super { };

No te dejes engañar:No significa que los componentes privados de la súper clase (como la variable de almacenamiento) se conviertan en públicos de una manera algo mágica. Privado Los componentes permanecerán privado, públicopermanecerá público.

objetos de la Sub clase puede hacer "casi" las mismas cosas que sus hermanos mayores creados a partir del Super clase. "Casi" porque el hecho de ser una subclase también significa que la la clase perdió el acceso a los componentes privados de la superclase.No podemos escribir una función miembro del Sub clase que sería capaz de manipular directamente la variable de almacenamiento.

Esta es una restricción muy seria.¿Hay algún trabajo alrededor?

.

El tercer nivel de acceso se llama protegido.La palabra clave protected significa que el componente marcado con ella Se comporta como público cuando lo usa cualquiera de las subclases y parece privado para el resto del mundo.. -- Esto es cierto sólo para las clases heredadas públicamente (como la clase Super en nuestro ejemplo). --

class Super {
protected:
    int storage;
public:
    void put(int val) { storage = val;  }
    int  get(void)    { return storage; }
};

class Sub : public Super {
public:
    void print(void) {cout << "storage = " << storage;}
};

int main(void) {
    Sub object;

    object.put(100);
    object.put(object.get() + 1);
    object.print();
    return 0;
}

Como puede ver en el código de ejemplo, agregamos una nueva funcionalidad al 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 alcance de la función principal, la variable permanece oculta de todos modos, por lo que si escribe algo como:

object.storage = 0;

El compilador le informará que es un error: 'int Super::storage' is protected.

Finalmente, el último programa producirá el siguiente resultado:

storage = 101
Member in base class : Private   Protected   Public   

tipo de herencia : Objeto hereda como :

Private            :   Inaccessible   Private     Private   
Protected          :   Inaccessible   Protected   Protected  
Public             :   Inaccessible   Protected   Public

1) Herencia públicos:

a. Los miembros privados de la clase Base no son accesibles en la clase derivada.

b. Los miembros protegidos de la clase Base permanecen protegidos en clase derivada.

c. 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 través objeto de la clase derivada.

2) Protegido Inheritance :

a. Los miembros privados de la clase Base no son accesibles en la clase derivada.

b. Los miembros protegidos de la clase Base permanecen protegidos en clase derivada.

c. 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 utilizar los miembros públicos de la clase base a través de objeto de clase derivada; pero están disponibles a subclase de Derivados.

3) La herencia privada

a. Los miembros privados de la clase Base no son accesibles en la clase derivada.

b. 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 se puede acceder a través de otras clases de objeto de clase derivada, ya que son privadas de la clase derivada. Por lo tanto, incluso subclase de Derivados clase no puede acceder a ellos.

Los modelos de herencia Pública una relación es-un. Con

class B {};
class D : public B {};

cada D es un B.

Los modelos de herencia privada un IS-implementada en base de la relación (o lo que se llama). Con

class B {};
class D : private B {};

a b_ es no a protected, pero cada <=> utiliza su <=> en su aplicación. herencia privada siempre se puede eliminar mediante el uso de la contención en su lugar:

class B {};
class D {
  private: 
    B b_;
};

Esta <=>, también, se puede implementar utilizando <=>, en este caso utilizando su <=>. La contención es un acoplamiento menos apretado entre los tipos que la herencia, por lo que en general se prefiere. A veces, el uso de la contención en lugar de la herencia privada no es tan conveniente como herencia privada. A menudo, eso es una mala excusa para ser perezoso.

No creo que nadie sepa lo que <=> modelos de herencia. Por lo menos yo no he visto ninguna explicación convincente aún.

Si hereda públicamente de otra clase, todo el mundo sabe que está heredando y puede ser utilizado por cualquier persona polimórfica a través de un puntero de clase base.

Si hereda protectedly sólo sus hijos clases serán capaces de usar que polimórfica.

Si hereda de forma privada sólo para usted será capaz de ejecutar métodos de la clase padre.

Lo que básicamente simboliza el conocimiento del resto de las clases tiene sobre su relación con su clase padre

miembros de datos protegidas pueden ser accedidos por cualquier clases que heredan de su clase. miembros de datos privados, sin embargo, no se puede. Supongamos que tenemos el siguiente:

class MyClass {
    private:
        int myPrivateMember;    // lol
    protected:
        int myProtectedMember;
};

Desde el interior de su extensión para esta clase, haciendo referencia a this.myPrivateMember no va a funcionar. Sin embargo, this.myProtectedMember voluntad. El valor todavía está encapsulado, por lo que si tenemos una instancia de esta clase llamada myObj, entonces myObj.myProtectedMember no funcionará, por lo que es similar en función a un miembro de datos privado.

Accessors    | Base Class | Derived Class | World
—————————————+————————————+———————————————+———————
public       |      y     |       y       |   y
—————————————+————————————+———————————————+———————
protected    |      y     |       y       |   n
—————————————+————————————+———————————————+———————
private      |            |               |    
  or         |      y     |       n       |   n
no accessor  |            |               |

y: accessible
n: not accessible

ejemplo para java ... Creo que una pequeña mesa vale más que mil palabras:)

Resumen:

  • Privado: nadie puede ver, excepto por dentro de la clase
  • Protegido: clases derivadas privada + pueden verlo
  • Público: el mundo puede verlo

Cuando heredar, puede (en algunos idiomas) cambiar el tipo de protección de un miembro de datos en cierta dirección, por ejemplo, a partir protegida a público.

Privado:

Los miembros privados de una clase base sólo se puede acceder por los miembros de esa clase base.

Público:

Los miembros públicos de una clase base se puede acceder por miembros de esa clase base, los miembros de su clase derivada, así como los miembros que están fuera de la clase base y clase derivada.

Protegido:

Los miembros protegidos de una clase base se puede acceder por los miembros de la clase base, así como los miembros de su clase derivada.


En resumen:

privado : Base

protegido : base + derivado

público : base + derivado + cualquier otro miembro

He encontrado una respuesta fácil y así pensé en publicar para mi futura referencia también.

Su uno de los enlaces http: //www.learncpp .com / CPP-tutorial / 115-herencia-y-ACCESS de especificadores /

class Base
{
public:
    int m_nPublic; // can be accessed by anybody
private:
    int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
protected:
    int m_nProtected; // can be accessed by Base member functions, or derived classes.
};

class Derived: public Base
{
public:
    Derived()
    {
        // Derived's access to Base members is not influenced by the type of inheritance used,
        // so the following is always true:

        m_nPublic = 1; // allowed: can access public base members from derived class
        m_nPrivate = 2; // not allowed: can not access private base members from derived class
        m_nProtected = 3; // allowed: can access protected base members from derived class
    }
};

int main()
{
    Base cBase;
    cBase.m_nPublic = 1; // allowed: can access public members from outside class
    cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
    cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
}

Básicamente se trata de 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 a los miembros públicos y protegidos de la base. Con la herencia privada, no se puede. Con protegida, la clase derivada y las clases derivadas de que puedan verlos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top