¿Cuáles son los especificadores de acceso? ¿Debo heredar con privado, protegido o público?

Estoy confundido sobre el significado de los modificadores de acceso con respecto a la herencia. ¿Cuál es la diferencia entre la herencia que implica las palabras clave private , protected y public ?

¿Qué son los especificadores de acceso?

Hay 3 access specifiers para una clase / struct / Union en C ++. Estos especificadores de acceso definen cómo se puede acceder a los miembros de la clase. Por supuesto, cualquier miembro de una clase es accesible dentro de esa clase (dentro de cualquier función miembro de esa misma clase). Avanzando hacia el tipo de especificadores de acceso, estos son:

Público : los miembros declarados como públicos son accesibles desde fuera de la clase a través de un objeto de la clase.

Protegido : los miembros declarados como Protegidos son accesibles desde fuera de la clase PERO solo en una clase derivada de él.

Privado : solo se puede acceder a estos miembros desde dentro de la clase. No se permite el acceso externo.

Un ejemplo de código fuente:

 class MyClass { public: int a; protected: int b; private: int c; }; int main() { MyClass obj; obj.a = 10; //Allowed obj.b = 20; //Not Allowed, gives compiler error obj.c = 30; //Not Allowed, gives compiler error } 

Especificadores de herencia y acceso

La herencia en C ++ puede ser uno de los siguientes tipos:

  • Herencia Private
  • Herencia Public
  • Herencia Protected

Estas son las reglas de acceso de los miembros con respecto a cada una de estas:

Primera y más importante regla Private miembros Private de una clase nunca son accesibles desde ningún lado excepto los miembros de la misma clase.

Herencia pública:

Todos los miembros Public de la clase base se convierten en miembros Public de la clase derivada &
Todos los miembros Protected de la clase base se convierten en miembros Protected de la clase derivada.

es decir, no hay cambio en el acceso de los miembros. Las reglas de acceso que discutimos anteriormente se aplican luego a estos miembros.

Ejemplo de código:

 Class Base { public: int a; protected: int b; private: int c; }; class Derived:public Base { void doSomething() { a = 10; //Allowed b = 20; //Allowed c = 30; //Not Allowed, Compiler Error } }; int main() { Derived obj; obj.a = 10; //Allowed obj.b = 20; //Not Allowed, Compiler Error obj.c = 30; //Not Allowed, Compiler Error } 

Herencia Privada:

Todos los miembros Public de la clase base se convierten en miembros Private de la clase derivada &
Todos los miembros Protected de la clase base se convierten en miembros Private de la clase derivada.

Un ejemplo de código:

 Class Base { public: int a; protected: int b; private: int c; }; class Derived:private Base //Not mentioning private is OK because for classes it defaults to private { void doSomething() { a = 10; //Allowed b = 20; //Allowed c = 30; //Not Allowed, Compiler Error } }; class Derived2:public Derived { void doSomethingMore() { a = 10; //Not Allowed, Compiler Error, a is private member of Derived now b = 20; //Not Allowed, Compiler Error, b is private member of Derived now c = 30; //Not Allowed, Compiler Error } }; int main() { Derived obj; obj.a = 10; //Not Allowed, Compiler Error obj.b = 20; //Not Allowed, Compiler Error obj.c = 30; //Not Allowed, Compiler Error } 

Herencia Protegida:

Todos los miembros Public de la clase base se convierten en miembros Protected de la clase derivada y
Todos los miembros Protected de la clase base se convierten en miembros Protected de la clase derivada.

Un ejemplo de código:

 Class Base { public: int a; protected: int b; private: int c; }; class Derived:protected Base { void doSomething() { a = 10; //Allowed b = 20; //Allowed c = 30; //Not Allowed, Compiler Error } }; class Derived2:public Derived { void doSomethingMore() { a = 10; //Allowed, a is protected member inside Derived & Derived2 is public derivation from Derived, a is now protected member of Derived2 b = 20; //Allowed, b is protected member inside Derived & Derived2 is public derivation from Derived, b is now protected member of Derived2 c = 30; //Not Allowed, Compiler Error } }; int main() { Derived obj; obj.a = 10; //Not Allowed, Compiler Error obj.b = 20; //Not Allowed, Compiler Error obj.c = 30; //Not Allowed, Compiler Error } 

Recuerde que las mismas reglas de acceso se aplican a las clases y miembros en la jerarquía de herencia.


Puntos importantes a tener en cuenta:

– La especificación de acceso es por clase, no por objeto

Tenga en cuenta que la especificación de acceso C ++ funciona por clase y no por objeto.
Un buen ejemplo de esto es que en un constructor de copia o función de operador de Asignación de copia, se puede acceder a todos los miembros del objeto que se está pasando.

– Una clase derivada solo puede acceder a los miembros de su propia clase base

Considere el siguiente ejemplo de código :

 class Myclass { protected: int x; }; class derived : public Myclass { public: void f( Myclass& obj ) { obj.x = 5; } }; int main() { return 0; } 

Da un error de comstackción:

prog.cpp: 4: error: ‘int Myclass :: x’ está protegido

Porque la clase derivada solo puede acceder a miembros de su propia clase base . Tenga en cuenta que el objeto obj se pasa aquí no está relacionado con la función de clase derived a la que se accede, es un objeto totalmente diferente y, por lo tanto, la función miembro derived no puede acceder a sus miembros.


¿Qué es un friend ? ¿Cómo afecta el friend las reglas de especificación de acceso?

Puede declarar una función o clase como friend de otra clase. Cuando lo hace, las reglas de especificación de acceso no se aplican a la clase / función friend ed. La clase o función puede acceder a todos los miembros de esa clase en particular.

Entonces, ¿el friend rompe la encapsulación?

No, no lo hacen, ¡al contrario, mejoran la encapsulación!

friend barco se utiliza para indicar un fuerte acoplamiento intencional entre dos entidades.
Si existe una relación especial entre dos entidades, por ejemplo, una necesita acceso a otros miembros private o protected , pero no desea que todos tengan acceso mediante el uso del especificador de acceso public entonces debe utilizar el envío de friend .

La explicación de Scott Meyers en Effective C ++ podría ayudar a entender cuándo usarlas, la herencia pública debería ser modelo es una relación, mientras que la herencia privada debería usarse para “is-implementation-in-terms-of”, por lo que no tiene para adherirse a la interfaz de la superclase, solo está reutilizando la implementación.