2009-09-01 17 views
10

¿Es un constructor público en una clase abstracta un código? Hacer que el constructor esté protegido proporciona todo el acceso del que puede hacer uso. El único acceso adicional que se haría público sería permitir que las instancias de la clase se declaren como variables en ámbitos que no pueden acceder a sus miembros protegidos, pero las instancias de clases abstractas no se pueden declarar en absoluto.¿Es un constructor público en una clase abstracta un código?

+0

¿Cómo se pueden declarar las variables de una clase abstracta? ¿Me estoy perdiendo de algo? – sbi

+0

Creo que OP significa métodos, como en 'métodos de miembros protegidos '. – quamrana

+0

Todavía no lo entiendo. ¿Podrías mostrar un ejemplo? – sbi

Respuesta

4

Mi opinión sería que el constructor público podría ser confuso y, como dices, hacerlo protegido sería correcto. Diría que un constructor protegido refuerza correctamente la impresión de que el único uso sensato de una clase abstracta es derivar de él.

De hecho, solo necesita declarar un constructor en una clase abstracta si necesita hacer algo, ej. inicializar sus propios miembros privados. Entonces esperaría que haya otras funciones de miembros protegidas que sean útiles para las clases derivadas.

EDIT:

puesto que no se ha publicado ningún código y @sbi pedido un poco en un comentario a OP, pensé que iba a publicar algunos:

class Base: 
{ 
public:   // The question is: should the ctor be public or protected? 
// protected: 
    Base():i(0){} // ctor is necessary to initialise private member variable 
public: 
    virtual ~Base(){} // dtor is virtual (but thats another story) 
        // pure virtual method renders the whole class abstract 
    virtual void setValue(void)=0; 
protected: 
    int getValue(void){ return i;} 
private: 
    int i; 
}; 

Base b1; // Illegal since Base is abstract, even if ctor is public 
Base& b2=makeBase(); //We can point to, or refer to a Base 
b2.setValue(); // We're not sure what this does, but we can call it. 
b2.getValue(); // Illegal since getValue is protected 
3

Como dices, no es necesario proporcionar el constructor público de la clase abstracta, ni se puede usar incorrectamente, si proporcionas el constructor público.

Sin embargo, puede considerar declarar el constructor como público como recomendación para estructurar clases derivadas del resumen.

+2

¿Puedes explicar tu segunda oración? No entiendo cuál podría ser la recomendación. – quamrana

+1

Creo que los directores públicos recomendarán la implementación de clases como un medio para diseñar la interfaz pública. Al igual, una clase abstracta de "Ventana" podría tener un editor público que tenga un parámetro "Ventana * principal". Se recomendará derivar clases para proporcionarlo también como un constructor público, que será parte de la interfaz. –

+0

Pensé que podría ser el caso, diría que está mal. Yo diría que en el caso de un ctor, debería estar protegido y tomar los parámetros que necesita, independientemente de lo que deberían hacer las clases derivadas. Sin embargo, cualquier otra función de miembros virtual puros públicos ** debe ser una indicación fuerte de que una clase hoja debe implementar estos con (obviamente) el mismo nivel de acceso y parámetros. – quamrana

11

He leído en al menos una guía de codificación que los constructores de clases abstractas no deberían ser públicas. Creo que esa regla tiene sentido por el motivo que usted dio.

Sin embargo, no me puedo imaginar un escenario donde hacerlo público haría que las cosas salieran mal. Así que no iría tan lejos como para decir que es un olor a código. Veo el constructor protegido como una propiedad "agradable de tener" :)

+1

De acuerdo, el constructor protegido explicita el hecho de que la clase no se puede instanciar directamente, por lo que es una "buena propiedad" desde el punto de vista del programador, incluso si el compilador realmente no se preocupa por ella. –

+2

Las pautas de codificación se supone que lo protegen de las cosas malas que podrían suceder. Como no puedes crear una clase abstracta, no veo de qué te está protegiendo esta guía y, por lo tanto, me siento arbítaria. –

+0

Dicen que al hacerlo protegido, usted hace explícito que no puede ser utilizado por las clases derivadas. Sospecho que es una lógica similar a la del operador miembro new y delete: son miembros implícitamente estáticos, pero es bueno hacerlos explícitamente estáticos. Por otro lado, la definición en clase de las funciones de los miembros está implícitamente en línea, y yo diría que es deficiente hacerlas explícitamente en línea. Al final, creo que este tema de constructor protegido es más una cuestión de gusto. –

0

tener cuidado sin embargo a explícitamente declarar/definir su constructor de copia privada/protegida. Si no lo hace, el compilador lo hará por usted. Ver scott meyers effective c++ elemento 6.

+0

¿No te refieres a destuctor en lugar de constructor? ¿Qué hay de malo en un constructor generado por defecto? – TimW

+0

Tienes razón. Lo siento, me refería al constructor de copias, de lo contrario todo no tiene sentido. – count0

0

Yo diría que es una mala señal por un par de razones.

La primera es que podría confundir a alguien haciéndole creer que puede llamar a esa rutina.

La segunda es que implica que el autor pensó que podía llamarlo. Ahora no sabe si esa fue una parte importante de su diseño o no.

+2

No creo que esos sean argumentos válidos. Nadie que sepa lo primero sobre el diseño de OO o C++ pensaría que podrías llamarlo y, en segundo lugar, el compilador emitirá un error en el momento en que lo intentes. –

2

Sé que una gran cantidad de personas obviamente no está de acuerdo, pero no creo que un editor de clases abstractas deba estar protegido a menos que la interfaz que está diseñando tenga un motivo específico para que todas las clases derivadas también tengan un ctor protegido.

La razón es que cuando diseñas una clase abstracta estás diseñando una interfaz para ser implementada por las clases derivadas. Las clases derivadas deberían implementar la interfaz exactamente como está diseñada en la clase base. La interfaz presentada por una clase base abstracta es un contrato; no rompas ese contrato.

O en otras palabras, si está cambiando la interfaz, ¿por qué se deriva de esa clase en primer lugar?

Esto es un poco de una respuesta religiosa, pero qué diablos. ;-)

+1

@Robert: Entiendo su razón dada aquí, pero creo que no se aplica a la ctor. Sí, otras funciones de miembro público y protegido (excluyendo el ctor y dtor) proporcionan interfaces que son un contrato y usted debe pensar dos veces antes de cambiarlas. – quamrana

3

La clase abstracta nunca se puede instanciar directamente debido a los métodos virtuales puros que declara. Entonces, declarar al constructor como protegido solo agrega consejos adicionales para los programadores.

Vi la recomendación de declarar el constructor como protegido here, en la guía de estilo de Google. Y he encontrado recomendaciones similares en algunos otros estándares de codificación corporativa. Así que esto parece una buena práctica.

Cuestiones relacionadas