Miembros privados y protegidos: C ++

¿Puede alguien aclararme la diferencia entre miembros privados y protegidos en las clases? Según las convenciones de mejores prácticas, entiendo que las variables y funciones que no se llaman fuera de la clase se deben hacer privadas, pero al mirar mi proyecto MFC, MFC parece favorecer a las protegidas.

¿Cuál es la diferencia y cuál debería usar?

Los miembros privados solo son accesibles dentro de la clase que los define.

Los miembros protegidos son accesibles en la clase que los define y en clases que heredan de esa clase.

Editar: Ambos también son accesibles por amigos de su clase, y en el caso de miembros protegidos, por amigos de sus clases derivadas.

Edición 2: usa lo que tenga sentido en el contexto de tu problema. Debe intentar que los miembros sean privados siempre que sea posible para reducir el acoplamiento y proteger la implementación de la clase base, pero si eso no es posible, entonces use miembros protegidos. Consulte las preguntas frecuentes de C ++ para una mejor comprensión del problema. Esta pregunta sobre las variables protegidas también podría ayudar.

Los miembros públicos de una clase A son accesibles para todos y para todos.

Los miembros protegidos de una clase A no son accesibles fuera del código de A, pero se puede acceder desde el código de cualquier clase derivada de A.

Los miembros privados de una clase A no son accesibles fuera del código de A, o del código de cualquier clase derivada de A.

Entonces, al final, elegir entre protegido o privado es responder a las siguientes preguntas: ¿Cuánta confianza está dispuesto a poner en el progtwigdor de la clase derivada?

De forma predeterminada , suponga que la clase derivada no es de confianza y haga que sus miembros sean privados . Si tiene una muy buena razón para otorgar acceso gratuito a las clases derivadas de la clase madre, puede protegerlas.

Se puede acceder a los miembros protegidos desde clases derivadas. Los privados no pueden.

 class Base { private: int MyPrivateInt; protected: int MyProtectedInt; public: int MyPublicInt; } class Derived : Base { public: int foo1() { return MyPrivateInt;} // Won't compile! int foo2() { return MyProtectedInt;} // OK int foo3() { return MyPublicInt;} // OK }; class Unrelated { private: Base B; public: int foo1() { return B.MyPrivateInt;} // Won't compile! int foo2() { return B.MyProtectedInt;} // Won't compile int foo3() { return B.MyPublicInt;} // OK }; 

En términos de “mejores prácticas”, depende. Si incluso hay una ligera posibilidad de que alguien pueda querer derivar una nueva clase de la existente y necesite acceso a miembros internos, conviértelos en Protegidos, no en Privados. Si son privados, puede ser difícil heredar su clase fácilmente.

La razón por la cual MFC favorece a las protegidas es porque es un marco. Probablemente desee subclasificar las clases de MFC y, en ese caso, se necesita una interfaz protegida para acceder a los métodos que no son visibles para el uso general de la clase.

Todo depende de lo que quieras hacer y de lo que quieras que las clases derivadas puedan ver.

 class A { private: int _privInt = 0; int privFunc(){return 0;} virtual int privVirtFunc(){return 0;} protected: int _protInt = 0; int protFunc(){return 0;} public: int _publInt = 0; int publFunc() { return privVirtFunc(); } }; class B : public A { private: virtual int privVirtFunc(){return 1;} public: void func() { _privInt = 1; // wont work _protInt = 1; // will work _publInt = 1; // will work privFunc(); // wont work privVirtFunc(); // wont work protFunc(); // will work publFunc(); // will return 1 since it's overridden in this class } } 

Los atributos y métodos marcados como protected son, a diferencia de los privados, aún visibles en subclases.

A menos que no desee usar o brinde la posibilidad de anular el método en posibles subclases, las haría private .

Los miembros protegidos solo pueden acceder a los descendientes de la clase, y por código en el mismo módulo. Solo se puede acceder a los miembros privados por la clase en la que están declarados y por código en el mismo módulo.

Por supuesto, las funciones de amigo tiran esto por la ventana, pero bueno.

los miembros privados solo son accesibles desde dentro de la clase, los miembros protegidos son accesibles en la clase y las clases derivadas. Es una característica de la herencia en los lenguajes OO.

Puede tener herencia privada, protegida y pública en C ++, que determinará a qué clases derivadas puede acceder en la jerarquía de herencia. C #, por ejemplo, solo tiene herencia pública.

Por supuesto, eche un vistazo a la pregunta Variables del miembro protegido . Se recomienda utilizar privado como predeterminado (al igual que las class C ++) para reducir el acoplamiento. Las variables de miembros protegidas son siempre una mala idea, las funciones de miembro protegidas se pueden usar, por ejemplo, para el patrón de Método de plantilla.

privado = accesible únicamente por la nave nodriza (clase base) (es decir, solo mi padre puede ir a la habitación de mis padres)

protected = accesible por la nave nodriza (clase base), y sus hijas (es decir, solo mi padre puede ir a la habitación de mis padres, pero le dio permiso a su hijo para entrar al dormitorio de los padres)

público = accesible por la nave nodriza (clase base), hija y todos los demás (es decir, solo mis padres pueden ir a la habitación de mis padres, pero es una fiesta en casa – mi casa su casa)

Como no se necesita ninguna función de miembro público para recuperar y actualizar miembros protegidos en la clase derivada, esto aumenta la eficacia del código y reduce la cantidad de código que necesitamos escribir. Sin embargo, se supone que el progtwigdor de la clase derivada debe estar al tanto de lo que está haciendo.

Se puede acceder al miembro privado solo en la misma clase donde ha declarado dónde se puede acceder como miembro protegido en la clase donde se declara junto con las clases heredadas por él.

  • Privado : es un especificador de acceso. Por defecto, las variables de instancia (miembro) o los métodos de una clase en c ++ / java son privados. Durante la herencia, el código y los datos siempre se heredan pero no se puede acceder fuera de la clase. Podemos declarar a nuestros miembros de datos como privados para que nadie pueda hacer cambios directos a nuestras variables miembro y podemos proporcionar captadores y establecedores públicos para cambiar a nuestros miembros privados. Y este concepto siempre se aplica en la regla de negocios.

  • Protegido : también es un especificador de acceso. En C ++, los miembros protegidos son accesibles dentro de la clase y a la clase heredada, pero no fuera de la clase. En Java, los miembros protegidos son accesibles dentro de la clase, a la clase heredada, así como a todas las clases dentro del mismo paquete.

Los miembros y amigos de cualquier clase derivada de esa clase base pueden acceder a un miembro protegido de la clase base no estática mediante uno de los siguientes:

  • Un puntero a una clase derivada directa o indirectamente
  • Una referencia a una clase derivada directa o indirectamente
  • Un objeto de una clase derivada directa o indirectamente

private es preferido para los datos de los miembros. Los miembros de las clases de C ++ son private por defecto.

public es preferido para las funciones de miembro, aunque es una cuestión de opinión. Al menos algunos métodos deben ser accesibles. public es accesible para todos. Es la opción más flexible y menos segura. Cualquiera puede usarlos, y cualquiera puede abusar de ellos.

private no es accesible en absoluto. Nadie puede usarlos fuera de la clase y nadie puede abusar de ellos. Ni siquiera en las clases derivadas.

protected es un compromiso porque se puede usar en clases derivadas. Cuando deriva de una clase, tiene una buena comprensión de la clase base y tiene cuidado de no hacer un mal uso de estos miembros.

MFC es un contenedor de C ++ para Windows API, prefiere public y protected . Las clases generadas por el asistente de Visual Studio tienen una fea combinación de miembros protected , public y private . Pero hay algo de lógica en las clases de MFC.

Los miembros como SetWindowText son public porque a menudo necesita acceder a estos miembros.

Los miembros, como OnLButtonDown , manejan las notificaciones recibidas por la ventana. No se debe acceder, por lo tanto están protected . Aún puede acceder a ellos en la clase derivada para anular estas funciones.

Algunos miembros tienen que hacer subprocesos y ciclos de mensajes, no se debe acceder ni anular, por lo que se declaran como private

En estructuras C ++, los miembros son public por defecto. Las estructuras se usan generalmente solo para datos, no para métodos, por lo tanto, public statement public se considera segura.

los modificadores de acceso privado y protegido son uno y lo mismo solo que se puede acceder a los miembros protegidos de la clase base fuera del scope de la clase base en la clase secundaria (derivada). También aplica lo mismo a la herencia. Pero con el modificador privado solo se puede acceder a los miembros de la clase base en el scope o código de la clase base y su amigo solo funciona ” ”