2012-09-04 2 views
5

Eventuali duplicati:
Inline functions in C++Cosa succede se implemento una classe nel file di intestazione?

Cosa significa il compilatore fare se implementano completamente una classe nel suo file di intestazione? Un esempio tipico segue:

class MyException 
{  
public: 
    explicit MyException(const char* file, int line) file(file), line(line) {}; 
    const char* getFile() const { return file }; 
    int getLine() const { return line }; 
private: 
    const char* const file; 
    const int line; 
}; 

La mia intenzione è quella di utilizzare la classe in questo modo: throw MyException(__FILE__, __LINE__).

Includo questo file di intestazione in ogni file .cpp. Suppongo che il compilatore compilerà la classe tante volte quante sono definite e includerà il codice macchina (identico) in ogni file oggetto che produce. Ora, cosa farà il linker? Ho provato un esempio più semplice (senza tutti quei fastidiosi const) e ha compilato bene.

Cosa accadrebbe se, invece di una semplice classe, implementassi una funzione C a tre schermate in un file di intestazione? E l'ultima domanda, dovrei dividere il mio esempio in file .h e .cpp?

+7

I metodi implementati nella definizione della classe sono in linea. –

+1

Per una classe breve come questa non ha senso dividerla in .h e .cpp. – alfa

+0

Passerà bene, a condizione che non includiate la vostra eccezione in 2 librerie e lanciate questa execzione sui limiti della libreria su un sistema Linux. Il runtime considererà la versione 2 dell'eccezione come diversa e un catch (MyException &) nella libreria A potrebbe non funzionare per una proiezione MyException dalla libreria B – gastush

risposta

3

Una definizione di classe non produce alcun codice. Mostra semplicemente agli utenti della classe come è strutturata, in modo che possano generare il codice appropriato per manipolarlo.

Sono le funzioni membro della classe che generano il codice. Quando si definisce una funzione membro all'interno della definizione della classe, essa fornisce alla funzione una dichiarazione implicita inline.

Una chiamata di funzione può essere compilato e collegato in uno dei due modi:

(1) Una singola copia del codice funzione con un'istruzione assembly RETURN alla fine può essere posizionato nell'immagine, e un CALL le istruzioni di assemblaggio possono essere collocate (insieme al passaggio param e al trasferimento del valore di ritorno) nel sito di chiamata per trasferire il controllo a questo codice.

o

(2) Una copia dell'intero attuazione funzione può sostituire l'intera chiamata di funzione al sito di chiamata.

Una funzione dichiarata inline è un consiglio al compilatore di farlo nel modo seguente. Inoltre una dichiarazione inline consente di definire la funzione in più unità di traduzione (quindi può essere inserita in un file di intestazione condiviso). Affinché il compilatore abbia la possibilità di implementare il secondo metodo, ha bisogno di una copia dell'implementazione della funzione in fase di compilazione. Questo non è disponibile se l'implementazione della funzione è in un'unità di traduzione straniera.

Va anche notato che i compilatori moderni fanno cose complicate con funzioni dichiarate in linea. Vedi:

http://gcc.gnu.org/onlinedocs/gcc/Inline.html

+2

C'è una sottile differenza tra una funzione inline e una funzione inline. –

+0

È importante aggiungere che le funzioni inline _may_ essere espanse in linea. Non saranno _ essere ... Ma anche le funzioni non inline possono essere espanse in linea. – jcoder

+1

Il significato più importante di 'inline' è che la funzione può essere definita in più unità di traduzione e il compilatore/linker/qualsiasi cosa è richiesta per produrre una sola copia nel programma finale. Ciò è direttamente rilevante per la domanda (dato che i membri della classe sono implicitamente in linea, e quindi la definizione della classe può essere inclusa da più unità di traduzione), mentre qualsiasi effetto che potrebbe avere sulla decisione di inline particolari chiamate di funzione non è rilevante. –

3

Tutti i metodi saranno metodi in linea. Potresti perdere un po 'di tempo nella compilation generale, ma va bene. Per quanto ne so, l'unico problema che si può verificare è se si dispone di una variabile membro non a costo statico. Quindi è necessario assegnare un luogo di archiviazione per esso (inserire una definizione e il valore iniziale se si desidera) presumibilmente in un .cpp oppure si otterranno errori del linker sulla definizione multipla.

Ho visto progetti di sola intestazione che avevano solo la funzione main() in un CPP, ma che era fortemente basata sui modelli.

3

Quando si implementano funzioni membro all'interno di un file di intestazione, tutte queste funzioni diventano implicitamente inline.

Che cosa significa e quali implicazioni ha?

Secondo, C++ 03 standard §7.1.3/4:

  • allude al compilatore che la sostituzione del corpo della funzione nel punto di chiamata è preferibile rispetto al solito meccanismo di chiamata di funzione.
  • Anche se la sostituzione in linea è omessa, vengono seguite le altre regole (in particolare una regola di definizione w.r.t) per inline.

Quindi sì, ogni unità di traduzione avranno la definizione delle inline function.This può risultato in aumento delle dimensioni dei vostri binari.

Di solito ogni buon compilatore tradizionale sostituirà corpo della funzione al punto di chiamata, se necessario, in modo funzioni inline marcatura solo per # 1 non è davvero una buona idea, ma se si desidera rendere il vostro intento chiaro per gli utenti della tua classe quindi puoi farlo definendo le funzioni all'interno dell'intestazione o contrassegnando esplicitamente le tue funzioni come inline.

dovrei dividere il mio esempio in .h e .cpp file?

Sì, questo è il solito modello di compilazione che la maggior parte dei progetti utilizzano, in cui si separa l'interfaccia (h) con l'applicazione (cpp) .Le interfacce sono condivisi con gli utenti del vostro codice come i file di intestazione mentre l'implementazione viene fornita sotto forma di file binari. Ad esempio, parte della misura fornisce una protezione alla proprietà intellettuale.
Questo è noto come Modello di separazione.

progetti C++ utilizzando i modelli di solito utilizzare il Inclusione Modello piuttosto che il modello di separazione dei soliti progetti di C++.