Domanda

A quanto pare (almeno secondo gcc -std=c99) C99 non supporta la funzione sovraccarico. La ragione per non sostenere qualche nuova funzionalità in C è solitamente compatibilità all'indietro, ma in questo caso non può pensare ad un solo caso in cui funzione sovraccarico romperebbe compatibilità. Qual è il ragionamento che sta dietro ad esclusione di questa funzionalità di base?

È stato utile?

Soluzione

Per capire il motivo per cui non si rischia di vedere un sovraccarico in C, potrebbe aiutare ad imparare meglio come overloading viene gestito dal C ++.

Dopo la compilazione del codice, ma prima che sia pronto per l'esecuzione, l'intermedio codice oggetto deve essere collegati. Ciò trasforma una base di dati grezzi di funzioni compilate e altri oggetti in un momento di caricare / file binario correre. Questo ulteriore passaggio è importante perché è il principio della modularità meccanismo a disposizione dei programmi compilati. Questo passaggio consente di prendere il codice da librerie esistenti e mescolare con la logica propria applicazione.

In questa fase, il codice oggetto potrebbe essere stato scritto in qualsiasi lingua, con qualsiasi combinazione di caratteristiche. Per rendere ciò possibile, è necessario avere una sorta di convenzione in modo che il linker è in grado di scegliere l'oggetto giusto quando un altro oggetto si riferisce ad esso. Se stai codifica in linguaggio assembly, quando si definisce un un'etichetta, questa viene utilizzato così, perché si presume di sapere cosa si sta facendo.

In C, le funzioni diventano i nomi dei simboli per il linker, in modo che quando si scrive

int main(int argc, char **argv) { return 1; }

il compilatore fornisce un archivio di codice oggetto, che contiene un oggetto chiamato main.

Questo funziona bene, ma significa che non si può avere due oggetti con lo stesso nome, perché il linker non sarebbe in grado di decidere quale nome dovrebbe usare. Il linker non sa nulla di tipi di argomento, e molto poco di codice in generale.

C ++ risolve questo codificando ulteriori informazioni nel nome del simbolo direttamente. Il tipo di ritorno e il numero e il tipo di argomenti vengono aggiunti al nome del simbolo, e si riferiscono a quel modo al punto di una chiamata di funzione. Il linker non ha bisogno di sapere questo è ancora accadendo, dal momento che, per quanto si può dire, la chiamata di funzione è inequivocabile.

Il rovescio della medaglia è che i nomi dei simboli non guardare nulla come i nomi delle funzioni originali. In particolare, è quasi impossibile prevedere ciò che il nome di una funzione di sovraccarico sarà così che è possibile collegare ad esso. Creare un collegamento a foriegn codice, è possibile utilizzare extern "C", che fa sì che le funzioni per seguire lo stile C di nomi di simboli, ma naturalmente non si può sovraccaricare una tale funzione.

Queste differenze sono legate al raggiungimento degli obiettivi di progettazione di ogni lingua. C è orientata verso la portabilità e l'interoperabilità. C va fuori del suo modo di fare le cose prevedibili e compatibili. C ++ è più fortemente orientata verso la costruzione di sistemi di ricchi e potenti, e non propriamente focalizzata su l'interazione con altri linguaggi.

Credo che sia improbabile per C di perseguire sempre qualsiasi funzione che produrrebbe il codice che è difficile da interagire con il C ++.

Modifica : Imagist chiede:

  

Sarebbe davvero essere meno portatile o   più difficile interagire con un   funzione se si risolto int main (int   argc, char ** argv) a qualcosa di simile   main-int-int-char ** anziché principale   (E questo fosse parte dello standard)?   Non vedo un problema qui. Infatti,   mi sembra che questo ti dà   ulteriori informazioni (che potrebbero essere utilizzate   per l'ottimizzazione e simili)

Per rispondere a questa, mi rivolgerò ancora a C ++ e il modo in cui si tratta di sovraccarichi. C ++ utilizza questo meccanismo, quasi esattamente come descritto, ma con un avvertimento. C ++ non standardizzare come alcune parti di se stesso dovrebbero essere attuate, e poi va a suggerire come alcune delle conseguenze di tale omissione. In particolare, C ++ ha un ricco sistema tipo, che comprende membri della classe virtuali. Come questa caratteristica dovrebbe essere attuata è lasciata agli scrittori del compilatore, e i dettagli della risoluzione vtable ha un forte effetto sulle firme di funzione. Per questo motivo, C ++ suggerisce deliberatamente scrittori del compilatore rendono nome storpiatura essere incompatibili tra loro attraverso compilers o stessi compilatori con differenti implementazioni di queste caratteristiche principali.

Questo è solo un sintomo del problema più profondo che mentre linguaggi di livello superiore come C ++ e C hanno sistemi di tipo dettagliato, il codice macchina livello inferiore è totalmente senza tipo. arbitrariamente sistemi di tipo ricchi sono costruiti in cima al binario tipizzato forniti a livello di macchina. Linker non hanno accesso al ricco informazioni di tipo a disposizione dei linguaggi di livello superiore. Il linker è completamente dipendente dal compilatore per gestire tutti i astrazioni tipo e produrre correttamente tipo privo di codice oggetto.

C ++ fa codificando tutte le informazioni necessarie tipo i nomi degli oggetti alterati. C, tuttavia, ha un obiettivo molto diverso, con l'obiettivo di essere una sorta di linguaggio assembly portatile. C preferisce quindi di avere una rigorosa corrispondenza uno a uno tra il nome dichiarato e il nome del simbolo oggetti risultante. Se C Mangled è nomi, anche in modo standardizzato e prevedibile, si dovrebbe andare a grandi sforzi per abbinare i nomi alterati per i nomi dei simboli desiderati, altrimenti si avrebbe dovuto spegnerlo come si fa in C ++. Questo sforzo supplementare arriva a quasi alcun beneficio, perché a differenza di C ++, sistema di tipo di C è abbastanza piccolo e semplice.

Allo stesso tempo, è praticamente una pratica standard per definire diverse funzioni C nome simile che variano solo dai tipi che prendono come argomenti. per un lungo esempio di solo questo, date un'occhiata alla OpenGL namespace.

Altri suggerimenti

Quando si compila un sorgente C, i nomi dei simboli rimarranno intatti. Se si introduce l'overloading di funzioni, è necessario fornire un nome tecnica mangling per evitare nome scontri. Di conseguenza, come C ++, avrete macchina generato i nomi dei simboli nel binario compilato.

Inoltre, C non dispone di tipizzazione forte. Molte cose sono implicitamente convertibili l'una all'altra in C. La complessità delle regole di risoluzione di sovraccarico potrebbe introdurre la confusione in questo tipo di linguaggio.

Un sacco di progettisti di linguaggi, me compreso, pensano che la combinazione di funzione di sovraccarico con le promozioni implicite di C può causare il codice che è heinously difficile da capire. Per le prove, guardare il corpo di conoscenze accumulate su C ++.

In generale, C99 era destinato ad essere una revisione modesto ampiamente compatibile con la pratica esistente. Sovraccarico sarebbe stata una abbastanza grande partenza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top