2008-10-22 29 views
200

¿Alguien me puede aclarar 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.Miembros privados y protegidos: C++

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

Respuesta

287

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: Use lo que tenga sentido en el contexto de su 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 C++ FAQ para una mejor comprensión del problema. This question about protected variables también podría ayudar.

+7

El enlace a C++ FAQ Lite se ha movido a https://isocpp.org/wiki/faq/basics-of-inheritance – avner

5

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

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

+1

Una clase derivada puede anular las funciones virtuales privadas de su base –

+0

Ah sí, tienes razón. ¡Gracias! – fhe

4

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.

4

miembros privados solo son accesibles desde dentro de la clase, los miembros protegidos son accesibles en la clase y 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.

44

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.

+3

Me permito diferir: si hay una leve posibilidad de que _no_ subclase vaya a necesitarla, hazla privada. A menos que intentes que tu clase sea subclasificada, utiliza el patrón de método de la plantilla. – xtofl

21

La razón por la que MFC favorece la protección 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.

105

Público miembros de una clase A son accesibles para todos.

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

privadas miembros de una clase A no son accesibles fuera del código de A, o desde el código de cualquier clase derivada de A.

Así que, al final, la elección entre protegido o privado está respondiendo a la siguiente preguntas: ¿Cuánta confianza está dispuesto a poner en el programador de la clase derivada?

Por defecto, asumen la clase derivada no es de fiar, y hacen sus miembros privada. Si tiene una muy buena razón para otorgar acceso gratuito a las clases derivadas de la clase madre, puede protegerlas.

+0

La clase derivada debe ser un tipo de su clase, y los datos protegidos de la clase base son parte de los datos de la clase derivada. Se espera que el escritor de la clase derivada maneje estos datos correctamente o sea un error. Los datos privados en una clase base son, sin embargo, algo que el escritor de la clase derivada no controla. – CashCow

+0

@CashCow 'los datos protegidos de la clase base son parte de los datos de la clase derivada. De hecho. ¿No es mejor, entonces, que el escritor de la clase derivada declare esos datos en su clase, en lugar de los míos? ... :-) ... 'Se espera que el escritor de la clase derivada maneje estos datos adecuadamente o es un error. En el patrón NVI, el objetivo es hacer que todo sea privado, incluidos los métodos, para limitar el daño que el escritor derivado de la clase podría hacer a la jerarquía. Los métodos protegidos ya son un problema potencial. No estoy convencido de que agravar esto usando el estado protegido sea el enfoque correcto. – paercebal

+0

Podría ser, lo que requeriría que tenga "captadores" virtuales en la clase base para acceder a ella. Y aunque puede tener clases intermedias para hacer las diferentes formas en que se puede implementar el patrón de datos, no siempre es práctico hacerlo. Por ejemplo, un "patrón", común en los lenguajes que no tienen un modificador "const" aunque no necesario la mayor parte del tiempo en C++ es tener una clase base de solo lectura y clases derivadas de escritura. En C++ esto también puede ser agradable simplemente porque quiere más de una manera posible de cargar (inicializar) los datos. – CashCow

8

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 
    } 
} 
4

Claro que echa un vistazo a la pregunta Protected Member Variables. Se recomienda utilizar privado como predeterminado (al igual que C++ class ses do) para reducir el acoplamiento. Las variables de miembro protegido generalmente son una mala idea, las funciones de miembros protegidas se pueden usar, por ej. el patrón de Método de plantilla.

+0

Es curioso, lo edité en mi publicación antes de ver el tuyo. Votos arriba porque las aves de una pluma tropiezan con el mismo enlace :) –

3

ya que no se necesita una función de miembro público para buscar y actualizar miembros protegidos en 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 programador de clase derivada es consciente de lo que está haciendo.

2

Se puede tener acceso 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.

0

A protegida miembro de la clase de base no estático se puede acceder por miembros y amigos de cualquier clases derivadas de esa clase base 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
+0

¿Qué valor agrega tu respuesta a las otras respuestas? –

2

privada: 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 reglas comerciales.

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.

0

los modificadores de acceso privado y protegido son uno y lo mismo que se puede acceder a los miembros protegidos de la clase base fuera del alcance de la clase base en la clase secundaria (derivada). También aplica lo mismo a la herencia. Pero con el modificador privada de los miembros de la clase base sólo se puede acceder en el alcance o el código de la clase base y sus funciones friend única '' ''

+2

¿Qué valor agrega tu respuesta sobre las otras respuestas? –

3

= accesible por la nave nodriza (clase base) privada Sólo (es decir, sólo mi padre puede entrar en la habitación de mi padre)

protegida = accesible por nodriza (clase base), y sus hijas (es decir, sólo mi padre puede ir a la habitación de mis padres, pero no dio hijo/permiso de la hija para entrar al dormitorio de los padres)

pública = accesible por nodriza (clase base), la hija, y todos los demás (es decir, sólo mi padre puede ir a la habitación de mis padres, pero es una fiesta en la casa - Mi Casa Su Casa)

Cuestiones relacionadas