2010-04-16 24 views
7

Deseo reenviar declarar una función miembro estático de una clase en otro archivo. Lo que queremos hacer es el siguiente:declaran hacia adelante función estática C++

BigMassiveHeader.h:

class foo 
{ 
    static void init_foos(); 
} 

Main.cpp:

class foo; 
void foo::init_foos(); 
int main(char** argv, int argc) 
{ 
    foo::init_foos() 
} 

Esta falla con "error C2027: uso de tipo indefinido 'foo' "

¿hay una manera de lograr lo que quiero hacer con fuera haciendo init_foos una función libre, o incluyendo BigMassiveHeader.h? (BigMassiveHeader.h está afectando notablemente el tiempo de compilación, y se incluye en todas partes.)

+0

si se debe incluir en el código de el .cpp o en BigHeader.h no deberían tener un efecto. Después de todo, ESTÁS usando #include guardias o #pragma una vez para que BigHeader.h solo se compile una vez, ¿no? – Kyte

+2

@Kyte Incluir guardias limita BigHeader.h a una vez por unidad de traducción donde está incluido. Si se incluye en muchos archivos fuente, deberá compilarse muchas veces. – KeithB

+0

Entonces, ¿sería posible dividir la definición de 'class foo' en otro archivo de encabezado? –

Respuesta

10

no se puede declarar adelante miembros de una clase, independientemente de si son o no estática.

+0

Ni siquiera es una declaración directa de 'foo :: init_foos();', sino más bien una declaración de una función global llamada 'init_foos()'. –

+6

Estrictamente hablando, el lenguaje C++ no tiene un término como "forward declare". En común, hablar "adelantar declarar" normalmente significa "declarar sin definir". Teniendo esto en cuenta, es posible "reenviar declarar" una función miembro. Cada vez que * define * una clase, está "declarando hacia adelante" sus funciones miembro [no en línea]. La respuesta correcta sería: no puede * declarar * a un miembro de la clase sin * definir * la clase. La respuesta eliminada de James McNellis fue en realidad la respuesta formalmente correcta. – AnT

+2

@AndreyT: la sección estándar 27.2 se titula "Declaraciones a futuro", y hay una entrada de índice en la edición especial TC++ PL. –

0

No, es necesario incluir la cabecera para eso. Lo siento.

utilizar una función gratuita si es necesario, o dividir la clase.

4

No se puede declarar adelante los miembros de su clase, pero se puede hacer un espacio de nombres y una función dentro de ese espacio de nombres y hacia adelante declare que.

namespace nsfoo 
{ 
    void init_foos(); 
} 

Su clase si es necesario podía amigo esta función.

2

Si usted tiene un BigMassiveHeader, se debe considerar dividirlo en varias SmallCompactHeaders. Si desea expresar que muchas clases y funciones pertenecen juntas semánticamente, puede ponerlas en el mismo espacio de nombres. Siempre puede proporcionar un encabezado de conveniencia que incluya todos sus encabezados pequeños.

+0

Estamos muy conscientes de esto. La refacturación de BigMassiveHeader es una deuda técnica que hemos heredado de nuestros predecesores, y estamos pagando en cuotas. Esto, de hecho, es pare de ese esfuerzo. –

0

Yo sé que no es el punto de la cuestión, pero si BigMassiveHeader.h no es probable que cambie mucho con el tiempo, usted debe echar un vistazo a precompiled headers

0

Como primer refactorización, que haría uso de una conexión función que llama a la función estática. No es como su principal método está recibiendo llamadas muchas veces, por lo que no se dará cuenta de una llamada adicional, y que hace que el menor cambio en el código existente.

Por supuesto, en realidad no dice lo que está tratando de hacer, sólo lo que quiere hacer. Si lo que estamos tratando de hacer es conseguir llamada una vez al iniciar la aplicación, utilizar la inicialización de objetos estáticos para que, en lugar de llamar en principal. Si lo que está tratando de hacer es conseguir llamada después se crean todos los objetos estáticos, entonces es más complicado.

Por inicialización objeto estático, me refiero a algo como tener esto en un archivo .cpp que tiene acceso a la definición de .Que sea un amigo y privada para evitar múltiples llamadas:

struct call_init_foos { 
    call_init_foos() { foo::init_foos(); } 
} call_init_foos_on_startup; 
0

transmitirlas declaración de un único método de una clase, debe declarar el método como parte de la clase (como lo que realmente es).

por ejemplo, en su caso, añadir a MAIN.CPP:

class foo 
{ 
public: 
    static void init_foos(); 
} 

no es el más bonito, pero que le ahorrará tener que incluir toda la cabecera ..

Cuestiones relacionadas