2010-04-16 37 views
7

Desidero inoltrare una funzione membro statico di una classe in un altro file. Quello che voglio fare è simile al seguente:inoltrare la funzione statica 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() 
} 

Questo fallisce con "l'errore C2027: uso di tipo non definito 'foo' "

C'è un modo per realizzare ciò che voglio fare facendo diventare init_foos una funzione gratuita, o includendo BigMassiveHeader.h? (BigMassiveHeader.h sta influenzando notevolmente il tempo di compilazione ed è incluso ovunque.)

+0

se includere il codice in il .cpp o in BigHeader.h non dovrebbe avere un effetto. Dopo tutto, stai usando #include guards o #pragma una volta così BigHeader.h viene compilato solo una volta, giusto? – Kyte

+2

@Kyte Includi le guardie limitano BigHeader.h a una volta per unità di traduzione in cui è inclusa. Se viene incluso in molti file sorgente, dovrà essere compilato molte volte. – KeithB

+0

Quindi sarebbe possibile scomporre la definizione di 'class foo' in un altro file di intestazione? –

risposta

10

Non è possibile inoltrare i membri di una classe, indipendentemente dal fatto che siano statici o meno.

+0

Non è nemmeno una dichiarazione diretta di 'foo :: init_foos();', ma piuttosto una dichiarazione di una funzione globale chiamata 'init_foos()'. –

+6

In senso stretto, il linguaggio C++ non ha un termine come "forward dichlare". In comune parlare "avanti dichiarare" normalmente significa "dichiarare senza definire". Tenendo conto di ciò, è possibile "inoltrare dichiarare" una funzione membro. Ogni volta che * definisci * una classe, stai "dichiarando in avanti" le sue funzioni membro [non in linea]. La risposta corretta sarebbe: non puoi * dichiarare * un membro della classe senza * definire * la classe. La risposta cancellata di James McNellis era in realtà quella formalmente corretta. – AnT

+2

@AndreyT: la sezione Standard 27.2 è intitolata "Dichiarazioni di inoltro" e c'è una voce di indice nell'edizione speciale TC++ PL. –

0

No, è necessario includere l'intestazione per quello. Scusate.

Utilizzare una funzione gratuita se è necessario, o dividere la classe.

4

Non è possibile inoltrare i membri della classe ma è possibile creare uno spazio dei nomi e una funzione all'interno di tale spazio dei nomi e inoltrare tale dichiarazione.

namespace nsfoo 
{ 
    void init_foos(); 
} 

La tua classe, se necessario, può essere d'aiuto per questa funzione.

2

Se si dispone di un BigMassiveHeader, si consiglia di dividerlo in più SmallCompactHeaders. Se vuoi esprimere che molte classi e funzioni appartengono insieme semanticamente, puoi metterle nello stesso spazio dei nomi. Puoi sempre fornire un'intestazione di convenienza che includa tutte le intestazioni piccole.

+0

Ne siamo ben consapevoli. Il refactoring di BigMassiveHeader è un po 'di debito tecnico che abbiamo ereditato dai predecessori e che stiamo pagando a rate. Questo, in effetti, è lo stesso di quello sforzo. –

0

io so che non è il punto della questione, ma se BigMassiveHeader.h non è destinata a cambiare molto nel corso del tempo, si dovrebbe dare un'occhiata a precompiled headers

0

Come primo refactoring, userei un libero funzione che chiama la funzione statica. Non è come se il tuo metodo principale venisse chiamato molte volte, quindi non ti accorgerai di una chiamata in più, e questo cambierebbe il meno il codice esistente.

Naturalmente, in realtà non si dice cosa si sta tentando di fare, solo ciò che si vuole fare. Se quello che stai cercando di fare è ottenere chiamato una volta all'avvio dell'applicazione, utilizzare l'inizializzazione dell'oggetto statico per quello, piuttosto che chiamarlo in main. Se quello che stai cercando di fare è ottenere chiamato dopo che tutti gli oggetti statici sono stati creati, quindi è più complicato.

Per inizializzazione di oggetti statici, intendo qualcosa come avere questo in un file .cpp che ha accesso alla definizione di .Ne fanno un amico e privato per evitare chiamate multiple:

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

di trasmettere la dichiarazione di un unico metodo di una classe, è necessario dichiarare il metodo come parte della classe (come lo è davvero).

per esempio, nel tuo caso, aggiungere al Main.cpp:

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

la sua non è la più bella, ma farà risparmiare dover includere l'intera intestazione ..

Problemi correlati