Perché puoi avere la definizione del metodo nel file di intestazione in C ++ quando in C non puoi?

16

In C, non è possibile avere la definizione / implementazione della funzione all'interno del file di intestazione. Tuttavia, in C ++ è possibile avere l'implementazione del metodo completo all'interno del file di intestazione. Perché il comportamento è diverso?

    
posta Joshua Partogi 09.03.2011 - 09:23
fonte

5 risposte

23

In C, se si definisce una funzione in un file di intestazione, tale funzione verrà visualizzata in ogni modulo compilato che include tale file di intestazione e un simbolo pubblico verrà esportato per la funzione. Quindi se la funzione additup è definita in header.h, e foo.c e bar.c entrambi includono header.h, quindi foo.o e bar.o includeranno entrambe le copie dell'additup.

Quando vai a collegare insieme questi due file oggetto, il linker vedrà che l'additup dei simboli è definito più di una volta e non lo permetterà.

Se dichiari che la funzione è statica, non verrà esportato alcun simbolo. I file oggetto foo.o e bar.o continueranno a contenere entrambe copie separate del codice per la funzione, e saranno in grado di usarli, ma il linker non sarà in grado di vedere alcuna copia della funzione, quindi non si lamenteranno Naturalmente, nessun altro modulo sarà in grado di vedere la funzione. E il tuo programma sarà gonfio di due copie identiche della stessa funzione.

Se dichiari la funzione solo nel file di intestazione, ma non la definisci, e poi la definisci in un solo modulo, il linker vedrà una copia della funzione, e ogni modulo del tuo programma sarà in grado di vederlo e usarlo. E il tuo programma compilato conterrà solo una copia della funzione.

Quindi puoi avere la definizione della funzione nel file di intestazione in C, è solo cattivo stile, cattiva forma e una cattiva idea a tutto tondo.

(Per "dichiarare", intendo fornire un prototipo di funzione senza un corpo, con "define" intendo fornire il codice effettivo del corpo della funzione, questa è la terminologia C standard).

    
risposta data 09.03.2011 - 10:47
fonte
24

C e C ++ si comportano molto allo stesso modo in questo senso - puoi avere inline di funzioni nelle intestazioni. In C ++, qualsiasi metodo il cui corpo si trova all'interno della definizione di classe è implicitamente inline . Se vuoi fare lo stesso in C, dichiara le funzioni static inline .

    
risposta data 09.03.2011 - 09:40
fonte
4

Il concetto di un file di intestazione richiede una piccola spiegazione:

O dai un file sulla riga di comando del compilatore, o fai un '#include'. La maggior parte dei compilatori accetta un file di comando con estensione c, C, cpp, c ++, ecc. Come file sorgente. Tuttavia, di solito includono un'opzione della riga di comando per abilitare anche l'uso di qualsiasi estensione arbitraria a un file sorgente.

Generalmente il file indicato sulla riga di comando è chiamato 'Origine', e quello incluso è chiamato 'Intestazione'.

Il passo del preprocessore in realtà li prende tutti e fa apparire tutto come un singolo grande file per il compilatore. Ciò che era nell'intestazione o nella fonte in realtà non è rilevante a questo punto. Di solito c'è un'opzione di un compilatore che può mostrare l'output di questo stage.

Quindi per ogni file che è stato fornito sulla riga di comando del compilatore, viene dato un enorme file al compilatore. Questo può avere codice / dati che occuperanno memoria e / o creeranno un simbolo a cui fare riferimento da altri file. Ora ognuno di questi genererà un'immagine 'oggetto'. Il linker può dare un "simbolo duplicato" se lo stesso simbolo si trova in più di due file oggetto che vengono collegati insieme. Forse questa è la ragione; non è consigliabile inserire il codice in un file di intestazione, che può creare simboli nel file oggetto.

I "in linea" sono solitamente in linea .. ma quando si esegue il debug potrebbero non essere in linea. Quindi, perché il linker non dà errori definiti multipli? Semplice ... Questi sono simboli "deboli" e fintanto che tutti i dati / codice per un simbolo debole di tutti gli oggetti hanno le stesse dimensioni e contenuto, il collegamento manterrà una copia e lascerà cadere la copia da altri oggetti. Funziona.

    
risposta data 09.03.2011 - 15:20
fonte
3

Puoi farlo in C99: le funzioni inline sono garantite da qualche altra parte, quindi se una funzione non è stata allineata, la sua definizione viene tradotta in una dichiarazione (ad esempio, l'implementazione viene scartata). E, ovviamente, puoi utilizzare static .

    
risposta data 09.03.2011 - 10:48
fonte
-4

Probabilmente per lo stesso motivo per cui devi mettere l'implementazione del metodo completo all'interno della definizione della classe in Java.

Potrebbero sembrare simili, con parentesi ondulate e molte delle stesse parole chiave, ma sono lingue diverse.

    
risposta data 09.03.2011 - 09:35
fonte

Leggi altre domande sui tag