2010-12-25 10 views

risposta

7

Alcuni motivi:

(1) il tempo di compilazione incrementale

Quando i progetti si sviluppano più grandi, gestendo il tempo di costruzione è problematico soprattutto per i progetti C++. Costruire 1 o 5 minuti dopo un piccolo cambiamento fa una grande differenza. Ciò è sottolineato dalla maggior parte dei cambiamenti nei progetti di grandi dimensioni che sono piccoli e richiedono un sacco di test. Aggiungete a ciò qualsiasi tentativo di TDD e refactoring, e siete una lumaca morta con scarpe siciliane.

La suddivisione in intestazione e corpo, e spostandolo in libs migliora enormemente i tempi di costruzione incrementali.

(2) Statica
Per molte cose che avete bisogno di una singola istanza di un tipo, vale a dire

// .cpp 
static Foo foo; 

Non c'è modo (che io sappia) che permette questo in un header- solo progetto. Le soluzioni specifiche del compilatore sono limitate, ad es. __declspec(selectany) in MSVC è limitato ai tipi POD.

(3) Attuazione nascondendo
CPP/separazione .h è l'unico modo per separare chiaramente un'interfaccia pubblica dai dettagli di implementazione. Puoi lanciare membri della classe in una sezione private, ma ciò non funziona per altre entità. (Anche l'intestazione/separazione del corpo perde, a meno che non aggiungiate tecniche aggiuntive come PIMPL, quindi questo argomento è un po 'debole IMO, ma ancora una volta, in un grande progetto mi mancherebbe molto questo metodo efficiente se imperfetto).


Grande questione, in ogni caso - hai riconosciuto che c'è qualcosa afoul con il C/C++ costruire il modello, che considero un'antica reliquia di implicazioni orribili.

Si dovrebbe provare fino a che punto è possibile spingere un modello "solo intestazione" (o, almeno, un "quasi solo intestazioni", per consentire statici). Potresti arrivare abbastanza lontano, inoltre sarebbe interessante ascoltare le persone che ci hanno provato.

Potrebbe valere la pena provare a utilizzare le librerie statiche per separare e incapsulare le implementazioni e altrimenti mantenere tutto il codice nelle intestazioni. Posso vedere alcuni problemi con questo, ma non è che il nostro attuale modus operandi sia privo di problemi.

+4

+1 per chiamare il modello di build/link C/C++ che è davvero molto –

2

I file di intestazione (.h) sono pensati per essere utilizzati per definire l'interfaccia in modo che le classi e il codice possano essere utilizzati in altre unità di traduzione. Se si posiziona l'implementazione nel file .h, si finisce con più copie dello stesso codice, compilate in ogni unità di traduzione che include quel file .h. Ciò sconfigge il punto di dividere il tuo codice in piccoli pezzi che possono essere studiati e sviluppati isolatamente.

+0

Penso che potrebbe essere ancora fatto, è possibile inserire l'interfaccia pubblica in intestazioni che includano le "intestazioni di implementazione", proprio come fa con le sottocartelle 'details \'. Senza l'uso intensivo delle interfacce, la separazione .h/.cpp non coincide perfettamente con la separazione interfaccia/implementazione. – peterchen

3

inserire tutto il codice in file .h. Contrariamente alla credenza popolare, questo non duplicherà il codice tra i file .obj. I compilatori moderni sono molto più intelligenti di così.

La compilazione è piuttosto un problema. Se hai 20 file .h tutti inclusi in main.cpp, la compilazione di main.cpp richiederà un po 'di tempo. E verrà ricompilato, inclusi tutti i 20 file di implementazione .h, ogni volta che uno dei file di inclusione cambia.

Poi c'è stile. Mi sembra solo sbagliato. Ma questa è una questione di preferenza.

Quindi ci sono riferimenti. Se ClassA utilizza ClassB e ClassB utilizza ClassA, quale includi per primo?

+0

Non vedo da dove arrivano i compilatori moderni. Una volta che hai più unità di traduzione che includono file di intestazione con implementazione, duplicherai il codice nei file oggetto. Sì, in teoria, questa duplicazione potrebbe essere rimossa, ma ciò dovrebbe essere fatto dal linker piuttosto che dal compilatore. –

+0

L'ipotesi sui ruoli del linker e del compilatore è piuttosto obsoleta. La generazione del codice link-time è stata ampiamente utilizzata per un decennio. Un modo scomodo di metterlo sarebbe che con LTCG il compilatore è solo un elaborato preprocessore: i file .obj in realtà non contengono codice macchina. E la rimozione del codice duplicato (e non necessario, ecc. Ecc.) È un dato di fatto. – martona

+0

tutti i suoni molto molto intelligenti - è solo un peccato che sia necessario far fronte al modello di build obsoleto di C/C++! –

Problemi correlati