2010-06-10 17 views
5

Tengo una clase base y varias clases derivadas. Las clases derivadas usan algunos datos comunes, ¿puedo simplemente poner esos datos comunes como miembros protegidos de la clase base? Sé que el miembro protegido rompe la encapsulación a veces, así que me pregunto si hay algún buen enfoque.miembro de datos protegidos comunes en la clase base?

Aquí está un ejemplo específico:

class Base{ 
public: 
    virtual void foo() = 0; 
    void printData(); 
protected: 
    std::vector<std::string> mData; 
} 

class Dr1 : public Base{ 
public: 
    virtual void foo(); //could change mData 
} 

class Dr2 : public Base{ 
public: 
    virtual void foo(); //could change mData 
} 

Si pongo MDATA en DR1 y Dr2 como miembro privado, entonces tengo que ponerlo en los dos, y no puede tener PrintData() de la base ya que printData() necesita acceso a mData a menos que haga que printData() sea virtual y tenga una función idéntica tanto en Dr1 como en Dr2, lo cual no tiene mucho sentido para mí.

¿Hay alguna manera mejor de abordar esto sin utilizar un miembro protegido? Gracias.

Respuesta

3

Un diseño a tener en cuenta es hacer mData privado, y agregar métodos protegidos a Base que proporcionan manipulaciones comunes a los datos que luego pueden ser utilizados por Dr1 y Dr2.

Pero hay muchas veces que tiene más sentido dejar mData como miembro protegido. El mejor enfoque dependerá en gran medida de los detalles de su clase.

0

Mientras tenga sentido que todas las clases derivadas tengan el miembro, tiene sentido ponerlo en la clase Base.

razones que veo por no ponerlo allí son:

  1. Si se congela la interfaz (la clase base abstracta), entonces se vería obligado a utilizar ese almacenamiento o romper la compatibilidad para sus usuarios.
  2. Para evitar forzar a sus usuarios a #include <string> y <vector>.
0

Creo que dar acceso a las subclases a sus datos está bien si no está exponiendo esta clase como una biblioteca para que otros subclases de. Si realmente quiere o necesita para ocultar la aplicación real de los datos de sus subclases, sin embargo, puede hacer mData privada y crear métodos de acceso a la misma que están protegidos:

class Base { 
protected: 
    // figure out what interface you want for your subclasses: 
    // do they need the whole enchilada? or can you give them 
    // a few more targeted kinds of modification routines? 
    // one example: 
    void add_data(const std::string& d) { mData.push_back(d); } 
private: 
    std::vector<std::string> mData; 
}; 
8

Esto está abierto a discusión considerable. Permitir que los datos sean protected se agregaron a C++ en gran parte porque Mark Linton lo quería para la biblioteca Interviews Windowing que estaba diseñando. Parecía encajar razonablemente bien con el resto del diseño de C++, por lo que (al parecer) Bjarne estuvo de acuerdo con la idea. Después de unos años, Mark prohibió el uso de miembros de datos protegidos en las entrevistas debido a la cantidad de errores que resultaron de su uso. Algún tiempo después de eso, Barbara Liskov dio una charla sobre problemas teóricos y prácticos con toda la noción.

En El Diseño y Evolución de C++, Bjarne llega a la conclusión de que: "En retrospectiva, creo que protected es un caso en el que dejo 'buenos argumentos' y la moda superar mi mejor juicio y mis reglas de oro para la aceptación de nuevas características "

En pocas palabras: Tengo una segunda y tercera idea sobre cómo hacer que sus datos protected. Puede parecer una buena idea ahora, pero el mantenimiento puede ser una historia bastante diferente.

+0

Muchas gracias por su respuesta y la interesante historia. Sí, el mantenimiento también es mi preocupación. Acepté la otra respuesta ya que user168715 señaló una forma de resolver el problema. – EXP0

1

He llegado a la conclusión de que los datos protegidos son tan malos como los datos públicos en una clase.Si alguna vez necesita cambiar los datos protegidos, va a romper todas las clases derivadas de la base. Esas clases derivadas son clientes de su clase base, al igual que los usuarios "públicos" normales. Sugiero escribir funciones de acceso protegidas a las que puedan llamar las clases derivadas. Esto le brinda todos los beneficios de las funciones de miembro público: puede cambiar su implementación sin interrumpir clientes, y puede agregar fácilmente instrumentación y verificación de errores si es necesario.

Cuestiones relacionadas