it-swarm.it

Cosa fare se odio i file di intestazione C ++?

Sono sempre stato confuso sui file di intestazione. Sono così strani: includi il file .h che non include .cpp ma .cpp sono in qualche modo anche compilati.

Di recente ho aderito a un progetto di gruppo e, naturalmente, sono stati utilizzati sia .h che .cpp.
Capisco che questo è molto importante, ma non posso convivere con il copia-incolla di ogni dichiarazione di funzione in ciascuna delle molteplici classi che abbiamo.

Come posso gestire in modo efficiente la convenzione a 2 file?
Ci sono degli strumenti che possono aiutare in questo, o cambiano automaticamente un file che appare come esempio qui sotto in .h e .cpp? (specificamente per MS VC++ 2010)

class A
{
...
    Type f(Type a,Type b)
    {
        //implementation here, not in another file!
    }
...
};

Type f(Type a)
{
     //implementation here
}
...
25
Oleh Prypin

È possibile utilizzare Lzz . È uno strumento da riga di comando che accetta le dichiarazioni scritte in una sintassi C++ e genera l'intestazione e i file di origine.

3
Mario Becerra

Scrivere più refactoring amichevole C++

In C++ non devi avere per usare le intestazioni. Puoi definire l'intero oggetto in un file come faresti con C # o Java. Gli sviluppatori C di solito mantengono solo le chiamate esterne in un file di intestazione. Tutte le chiamate interne sarebbero definite nel file .c. Allo stesso modo, è possibile riservare i file .h C++ per le classi/interfacce (classi astratte virtuali pure)/ecc. che devono essere condivisi all'esterno della DLL. Per classi/strutture/interfacce interne, ecc. Dovresti semplicemente includere il file .cpp che ti serve:

#include<myclass.cpp>

Questo non sembra essere l'approccio più popolare, ma è C++ legale. Sarebbe sicuramente una possibilità per tutto il tuo codice interno. Ciò consente al codice interno e all'insieme di classi di cambiare molto più radicalmente fornendo al contempo un'interfaccia più stabile per il codice esterno alla libreria/eseguibile con cui interagire.

Avere tutta la classe all'interno di un file renderà più facile fare ciò che vuoi. Non risolverà il problema della ridenominazione di un metodo e la ricerca in ogni luogo chiamato quel metodo, ma assicurerà di avere messaggi di errore più comprensibili. Niente di peggio che avere l'intestazione dichiarare un metodo in un modo, ma lo implementi in modo diverso. Altro codice che chiama il file di intestazione verrà compilato correttamente e otterrai un'eccezione di collegamento, mentre il file di implementazione sarà quello che si lamenta che il metodo non è stato definito. Quando definisci tutti i metodi in atto (nella dichiarazione di classe effettiva), otterrai lo stesso messaggio di errore indipendentemente dal file che lo include.

Potresti anche voler esaminare questa domanda: Buoni strumenti di refactoring per C++

Come C/C++ risolve i file di intestazione/implementazione

A livello C di base (e C++ è basato su quella base), i file di intestazione dichiarano la promessa di una funzione/struttura/variabile che è sufficiente per consentire a un compilatore di creare il file oggetto. Allo stesso modo i file di intestazione C++ dichiarano la promessa di funzioni, strutture, classi, ecc. È questa definizione che il compilatore utilizza per riservare spazio nello stack, ecc.

I file .c o .cpp hanno l'implementazione. Mentre il compilatore converte ogni file di implementazione in un file oggetto, ci sono hook in concetti non implementati (ciò che è stato dichiarato nell'intestazione). Il linker lega gli hook alle implementazioni in altri file oggetto e crea un file binario più grande che include tutto il codice (libreria condivisa o eseguibile).

VS specifico

Per quanto riguarda lavorare con quelli in Visual Studio, ci sono alcune procedure guidate che aiutano a rendere le cose un po 'più facili. La nuova procedura guidata di classe creerà la coppia di intestazione e file di implementazione corrispondenti. Esiste anche una funzione browser di classe che ti permetterà di dichiarare nuovi metodi. Inserirà la definizione nell'intestazione e lo stub di implementazione nel file .cpp. Visual Studio ha queste funzionalità da oltre un decennio (purché le abbia utilizzate).

16
Berin Loritsch

Diventa uno Java.

Se devi davvero continuare a sviluppare in C++, puoi provare a utilizzare un IDE. Spesso offrono alcuni meccanismi con cui è possibile aggiungere un metodo a una classe e posiziona automagicamente la dichiarazione nel file .h e la definizione nel file .cpp.

13
Paul Butcher

Potresti essere interessato al programma makeheaders di Hwaci (quelli che fanno SQLite e Fossil).

Dai anche un'occhiata a come è costruito Fossil per avere un'idea.

8
Benoit

Quando scrivi le prime righe di una nuova classe, di solito è perché ne hai bisogno in un posto solo in quel momento. In un secondo momento, potrebbe essere utilizzato in più luoghi, ma inizialmente non lo è.

Molte delle mie lezioni iniziano all'inizio del file .cpp corrente. Quando si è stabilizzato abbastanza per usarlo in più punti, lo incido in un'intestazione. Anche se spesso la classe scompare velocemente come sembrava.

5
Sjoerd

Il file Header (.h) descrive il interfaccia al codice, perché quello è il solo bit che altro codice vede.

Il file Source (.cpp) fornisce l'implementazione del codice che nessun altro deve conoscere.

includi il file .h che non include .cpp ...

Corretta.

Come consumatore di questo codice, hai solo bisogno del file Header in modo che il compilatore sappia cosa è disponibile in quel codice con cui lavorare. Il codice sorgente C++ non viene utilizzato in alcun modo, forma o forma a questo punto (o, almeno, non dovrebbe essere).

... ma .cpp sono in qualche modo anche compilati.

Sì, lo sono, ma completamente separatamente.

Il file .cpp di un modulo/libreria che si sta utilizzando viene compilato in un file Object (.o/.dll) dallo sviluppatore di quella libreria. Il file oggetto conterrà punti di entrata che hanno la stessa "forma" di quelli descritti nel file di intestazione.

Avrai bisogno di quel file Object quando arriverai a link il tuo eseguibile finito, a quel punto il Linker potrebbe prendere il contenuto del file Object e incorporarlo nel tuo eseguibile (che è per il link statico; il link dinamico ottiene più complicato)
Fondamentalmente il linker deve "unire i punti" tra i punti di ingresso che il tuo codice prevede per poter chiamare, in base a ciò che ha visto nel file Header e a ciò che è effettivamente in la biblioteca stessa).

0
Phill W.