2010-02-09 20 views
17

Se non c'è sovraccarico di funzione, il nome della funzione funge da indirizzo del codice funzione, e quando viene chiamata una funzione, il suo indirizzo è facile da trovare usando il suo nome. Tuttavia con l'overloading delle funzioni, in che modo esattamente il programma può trovare l'indirizzo corretto della funzione? Esiste una tabella nascosta simile alle tabelle virtuali che memorizza le funzioni sovraccaricate con il loro indirizzo? Molte grazie!In C++ come viene generalmente implementato l'overloading delle funzioni?

+4

Le persone che suggeriscono il nome di maciullamento sono sbagliate credo. Non è come se il compilatore maneggi il nome e fa una ricerca tra i nomi storti. Ha bisogno di dedurre i tipi corretti dai metodi disponibili. Una volta fatto, sa già quale metodo chiamare. Quindi utilizza il nome mangled come il passaggio _last_. Il nome mangling non è un prerequisito per determinare quale funzione di sovraccarico chiamare. –

+0

Forse questo commento dovrebbe andare in una delle risposte sbagliate a cui ti riferisci? – Manuel

+0

Ce ne sono troppi, quindi l'ho lasciato qui. –

risposta

11

Il compilatore può esaminare la chiamata e confrontarla con le implementazioni sovraccaricate esistenti note e scegliere quella giusta. Non c'è bisogno di una tabella dinamica, è tutto perfettamente eseguibile staticamente in fase di compilazione.

Aggiornamento: rimosso il mio tentativo di illustrare il concetto mostrando le funzioni con nomi diversi che il compilatore può scegliere.

+0

Le persone dicono che questo nome è Mangling. Cerca questa parola chiave. – SunnyShah

+4

Nome mangling è solo per distinguere tra nomi di identificatori, sovraccarico o meno. Lo scopo principale del manomissione dei nomi non è quello di evitare sovraccarichi, ma di evitare conflitti di denominazione. Nel caso di sovraccarico, il compilatore deve calcolare quale metodo chiamare e dove si trova la logica principale. Credo che l'OP volesse sapere se questa è stata una cosa in fase di compilazione/runtime. –

+0

Non è preciso, di solito è il linker che deve calcolare l'indirizzo di chiamata. La decorazione del nome è molto importante. Sì, esiste un'opportunità di omettere la richiesta di collegamento se la funzione si trova nella stessa unità di traduzione. Che ciò accada effettivamente è un dettaglio di implementazione. –

0

Si tratta, credo, realizzato attraverso nome storpiatura:

le funzioni che conosci come foo (INT) e foo (doppio) sono in realtà un nome simile a int_foo() e double_foo() (o simili, io Non sono completamente sicuro della particolare semantica impiegata per C++). Ciò significa che i simboli C++ sono in genere di un ordine di grandezza più grande dei nomi che vengono dati nel codice.

3

Le funzioni di overload sono risolte in fase di compilazione. Il compilatore trova una corrispondenza adatta per il dato insieme di parametri e chiama semplicemente la funzione corrispondente dal suo indirizzo (void foo(int) e void foo() sono praticamente due funzioni totalmente indipendenti - se hai foo(4) nel tuo codice, il compilatore sa quale funzione chiamare).

5

Se si parla di metodi di overload della stessa classe, in questo modo:

void function(int n); 
void function(char *s); 
... 

objectInstance->function("Hello World") 

Si tratta di un thingy fase di compilazione. Il compilatore sa (o in alcune situazioni, fa una buona ipotesi) a questo punto quale metodo chiamare.

Un commento che ho fatto nella domanda, ripeto qui.

Le persone che suggeriscono il nome di morsi sono errate, penso. Non è come se il compilatore maneggi il nome e fa una ricerca tra i nomi storti. Ha bisogno di dedurre i tipi corretti dai metodi disponibili. Una volta fatto, sa già quale metodo chiamare. Quindi utilizza il nome storpiato come passaggio ultimo. Il nome mangling non è un prerequisito per determinare quale funzione di sovraccarico chiamare.

+0

Alla persona che ha dato un -1. Almeno lascia un commento. Posso cancellare/modificare il post se l'informazione è inaccurata. Dammi una possibilità di imparare anche tu! –

+0

Immagino che quella persona (non io) abbia downvotato perché non hai dato una risposta chiara. Invece si dice "tempo di compilazione" e "il compilatore sa solo cosa fare", che è davvero un po 'impreciso. – AndiDog

+0

Bene, il nome di mangling è impreciso, IMO. Il meglio che possiamo dire è che il "compilatore sa". Ogni compilatore potrebbe avere la sua implementazione. –

-1

La firma della funzione è composto dal nome della funzione del parametro + (s) tipo (s)

12

Name mangling.

È tutto fatto in fase di compilazione. Il compilatore C++ in realtà modifica i nomi di funzione che si danno internamente, in modo che una funzione come

int foo(int a, float b, char c) 

ottiene internamente un nome equivalente a

func_foo_int_float_char() 

(il simbolo reale è di solito un po 'burocratese come [email protected]@@[email protected]).

Come si può vedere, il nome è decorato in base al numero esatto e ai tipi di parametri passati.Quindi, quando chiami una funzione, è facile per il compilatore osservare i parametri che stai passando, decorare il nome della funzione con loro e trovare il simbolo corretto. Ad esempio,

int a, b; float f; char c; 
foo(a,f,c) ; // compiler looks for an internal symbol called func_foo_int_float_char 
foo(a,b,c) ; // compiler looks for a symbol called func_foo_int_int_char 

Di nuovo, è tutto fatto completamente in fase di compilazione.

+6

È il contrario. Il compilatore prima guarda tutti i foos, ne sceglie uno che corrisponda a tutte le regole dello standard, e quindi forse emette un nome distorto per il linker. – UncleBens

+0

Molto informativo, grazie. – Dasaru

-1

Anche se nessuna funzione si sovraccarica, i compilatori di solito manipolano nomi di funzioni e variabili. Si chiama name mangling. Succede sia in C che in C++. Il nome della funzione può essere decorato in particolare (1) convenzione di chiamata, (2) sovraccarico della funzione C++, (3) funzione membro della classe.

GNU binutil c++filt può undecorate questo nome storpiato, e in Windows, non v'è UnDecorateSymbolName

-1

compilatori C++ utilizzano il nome mangling (nome diverso per ogni sovraccarico) di distinguere tra le funzioni del file oggetto. Per esempio

int test(int a){} 
int test(float a,float b){} 
int test(double a){} 
int testbam(double a){} 

produrrebbe i nomi dei simboli __Z4testi, __Z4testff, __Z4testd, __Z7testbamd. Questo nome mangling è altamente dipendente dal compilatore (purtroppo) e una delle molte ragioni per cui spesso C è preferito rispetto a C++.

Quando si chiama la funzione test, il compilatore corrisponde ai tipi di argomento e al numero di argomenti specificati rispetto a ciascun sovraccarico di funzione. I prototipi di funzione vengono quindi utilizzati per scoprire quale deve essere chiamato.