2011-11-02 16 views
10

En C++ y Objective-C, me he acostumbrado a declarar a futuro las clases necesarias que no necesitan definirse en el encabezado, y luego importar los archivos de cabecera que definen esas clases en los archivos de origen si es necesario.Desventajas de la declaración directa?

¿Alguna vez hay una situación en la que esta no sea una buena idea?

(Sé que la desventaja de la declaración directa es la usabilidad limitada de un tipo incompleto. A los fines de esta pregunta, supongamos que en el encabezado solo necesito usar la clase forward-declarated como un tipo incompleto).

+17

¿Menos oportunidad de tomar café durante una construcción completa? –

Respuesta

6

A veces se puede cambiar la semántica del programa sutilmente sin levantar cualquier error

class Foo; 

template < typename T> 
struct Trait 
{ 
    static const int MY_TYPE = -1; 
}; 

// Lets say this is Foo.h 
//class Foo 
//{ 
//}; 
//template<> 
//struct Trait<Foo> 
//{ 
// static const int MY_TYPE = 1; 
//}; 

void TestFunction(Foo& f) 
{ 
    std::cout << Trait<Foo>::MY_TYPE << std::endl; 
} 

Considere el código anterior y el código comentado vive en un encabezado. Si el encabezado está incluido, TestFunction imprimirá 1, de lo contrario -1

+0

+1 .. Probablemente más aplicable que mi comentario sabiendo lo que sé ahora sobre el proceso de pensamiento del PO. – Steve

+0

Cosas interesantes. Ese es el tipo de cosa que me dio curiosidad. – Luke

3

Una desventaja podría ser la falta de ocultación/encapsulación de la información.

Prefiero tener el archivo de encabezado más mínimo que pueda. Significa que no estoy obligado a continuar apoyando tantas funciones. Si quiero cambiar algo, y ese algo no se ha expuesto en el encabezado público, hay muchas más posibilidades de que pueda cambiarlo internamente a la clase sin afectar a nadie más.

EDIT:

Lucas pidió un ejemplo, así que aquí ya go:

Suponga que tiene una clase llamada Car. Y, para lo único que lo construyó fue para pasar del punto A al punto B. Yo, personalmente, preferiría mantener mi archivo de encabezado en: una clase llamada Car, y un método llamado Drive. Por la forma en que formuló su pregunta ("todas las clases que puedo"), esperaría encontrar clases como "DieselEngine", "PetrolEngine", "HybidEngine" y tal en su archivo de encabezado también. El problema con esto es que otras personas que trabajan en su proyecto (o, usted, con el tiempo) comienzan a usar esas clases expuestas. Ahora, dos años después, decides "Hrm ... que la clase PetrolEngine realmente me está causando problemas. Creo que voy a eliminarla y reemplazarla por la HybridEngine por completo en mi clase de auto" - bueno, ahora PetrolEngine está incluido en otros 100 archivos por razones que no comprende, y ahora está obligado a mantener a PetrolEngine (y a trabajar como solía hacerlo) para todos los otros tipos que lo usaron en algunos de los que no está seguro. - porque no tenía un "contrato" sólido de trabajo para la forma en que quería que esa clase se utilizara en primer lugar. Fue un detalle de implementación de lo que realmente quería lograr: construir un automóvil.

EDIT para hablar sobre los comentarios acerca de la ocultación de información:

Si todo lo que estamos haciendo es estrictamente prospectivas declarando el nombre de clase/struct - bueno, supongo que me gustaría preguntar "por qué" de nuevo. Si soy un consumidor de su archivo de encabezado y clase (es), y realmente no puedo hacer nada con esa clase, y no está expuesto como un parámetro o tipo de retorno de la API de su clase principal, entonces ¿por qué exponerlo en absoluto? ?

Si lo está utilizando para el tiempo de compilación, compruebe las comprobaciones de seguridad de las estructuras de datos opacas, bueno, eso es una cosa. Pero, la forma en que redactó su pregunta me hizo sonar como todo entró en el archivo de encabezado como una cuestión de rutina.

+0

No estoy seguro de saber a qué te refieres. ¿Podría dar un ejemplo? – Luke

+4

¿No ayudaría esta técnica a ocultar la información? Hay mucha menos información en una declaración directa que en una declaración completa. –

+2

¿Podría explicarnos cómo las declaraciones avanzadas rompen la encapsulación? Me parece que proporcionar solo el nombre de clase oculta mucha más información que proporcionar la definición completa. –

0

Ninguno, que yo sepa. La única desventaja, que ya ha cubierto, se trata de utilizar tipos incompletos. Como dices que no habrá usos que necesiten tipos completamente definidos, estarás bien, supongo.

0

Las declaraciones de reenvío son preferibles a la inclusión de archivo completo si no necesita la definición completa de la clase en el encabezado.La única desventaja que puedo pensar ya fue publicada como un comentario por @Stephen Darlington, que le daría 10 votaciones si pudiera. :)

0

Una de las desventajas es la pérdida potencial de memoria en los tipos declarados hacia adelante. Vea this question para más detalles. Los compiladores de Microsoft emiten warning C4150: deletion of pointer to incomplete type 'SomeType'; no destructor called en este caso.

+2

No es un problema con un compilador real. –

2

Las declaraciones de reenvío pueden aplicarse a muchas cosas: clases, funciones, variables/constantes globales (utilizando extern) y en C++ 11, enumeraciones.

La principal desventaja, hasta donde puedo ver, es la redundancia, porque la redundancia introduce más margen para errores, sin embargo, esto aplica de manera muy diferente dependiendo de lo que esté declarando hacia adelante.

Si tiene un error con la declaración directa de una clase, una global o una enumeración, el compilador debería recogerla (¡sí!).

Si tiene un error con la declaración de una función, entonces en C++ simplemente ha creado una sobrecarga (¡oups!).

Por lo tanto, diría que no hay una desventaja real para el reenvío de clases, globales o enumeraciones; sin embargo, cuando se trata de funciones, es mejor si se ajusta al #include, siempre puede crear encabezados que agrupen las funciones relacionadas para evitar crear demasiados archivos.

0

Quizás sea principalmente una cuestión de legibilidad para sus colegas que deberá continuar su trabajo de codificación.

Cuestiones relacionadas