2014-12-14 16 views
7

So che l'overloading non è possibile in C, e voglio sapere: perché le funzioni di overload all'interno della classe e al di fuori della classe sono trattate allo stesso modo in C++?Perché il sovraccarico non è possibile in C?

considerare questo caso in C++, dove le funzioni sono dichiarate fuori della classe:

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

Se C++ tratta ogni intestazione funzione unica, perché non può fare C come bene?

Credo che queste potrebbero essere il motivo:

  • sovraccarico funzione è stata introdotta in C++, in modo che non è disponibile in C.
  • polimorfismo è un concetto OOP, ma C non è orientato agli oggetti.

Ci sono motivi per l'indisponibilità di sovraccarico di funzione in C?

+0

Qui ci sono 3 domande molto diverse. Qual è il più importante per te? – anatolyg

+6

Ogni volta che ti chiedi perché una lingua (qualsiasi lingua, non solo C) non supporta una funzione trovata in una nuova lingua, la risposta è solitamente la stessa: (1) Confronta quella lingua con le lingue più vecchie, non più recenti. (2) Creare un elenco di funzionalità che questa lingua ha introdotto rispetto a quelle più vecchie. (3) Apprezzare quale progresso ha rappresentato la lingua per avere queste nuove funzionalità. (4) Renditi conto che questo è ciò che pensavano anche i progettisti, e ad un certo punto hanno deciso di tracciare una linea e chiamarla un giorno. –

+0

Ecco perché è stato inventato il C++. – iammilind

risposta

8

Forse la ragione più importante è la mancanza di arte nota. Ci sono pochissimi esempi di funzionalità aggiunte a C dal comitato standard che non sono state estensioni popolari prima né sono necessarie per scrivere codice strettamente conforme.

C'è un po 'vagamente definito "spirito di C", la logica C99 (V5.10) legge (pagina 3, emph mio.):

Alcune delle sfaccettature dello spirito di C può essere riassunto in frasi come:

  • Fidati del programmatore.
  • Non impedire al programmatore di fare ciò che deve essere fatto.
  • Mantieni la lingua piccola e semplice.
  • Fornire solo un modo per eseguire un'operazione.
  • Veloce, anche se non è garantito la portabilità.

Inoltre, C sforza di rimanere compatibile con vecchie revisioni; le dichiarazioni vecchio stile, ad esempio, sono state contrassegnate come obsolescenti in C89 ma fanno ancora parte di C11. Ibid, pagina 2:

Il codice esistente è importante, le implementazioni esistenti non lo sono. Esiste una grande quantità di codice C di notevole valore commerciale. È stato fatto ogni tentativo per garantire che la maggior parte di questo codice sia accettabile per qualsiasi implementazione conforme allo standard. Il Comitato C89 non voleva forzare la maggior parte dei programmatori a modificare i loro programmi C solo per averli accettati da un traduttore conforme.

Alcune differenze in C e C++ sono almeno in parte causati da funzione sovraccarico, per esempio il tipo di costanti carattere:

int foo(int); 
int foo(char); 
... 
    foo('x'); 

In C++, ciò richiede foo(char), ma in C, il tipo di 'x' è int, quindi o il risultato sarebbe piuttosto sorprendente, oppure 'x' doveva essere di tipo char, possibilmente interrompendo il codice esistente. Inoltre, probabilmente desideri alcune promozioni laddove hanno senso, ad es. se nell'ultimo esempio non è stata fornita la seconda dichiarazione di foo, verrà promosso lo 'x' su int e foo(int). Tali regole possono diventare complesse in dettaglio (è necessario convertire void * in modo implicito per le chiamate di funzione?). (Non un numero difficile, ma il capitolo sull'overload delle funzioni nello standard C++ (capitolo 13) nella bozza n3797 copre circa 30 pagine, il capitolo 5.2.2 sulle chiamate di funzione è notevolmente più lungo della corrispondente parte C standard.)

Praticamente ogni caratteristica di C è necessaria per un linguaggio minimale (beh, modulo storico legacy), c'è pochissimo zucchero sintattico; l'overloading delle funzioni potrebbe essere considerato tale (potresti nominare le tue funzioni foo_int e foo_char ecc. e chiamare quella corretta in modo esplicito).

I motivi che hai suggerito, sono circolari (e quindi non sono applicabili): C ha adottato alcune caratteristiche del C++ (ad esempio i prototipi di funzione); e l'overloading delle funzioni è stato introdotto in C++ perché C mancava (non si può dire "non fa parte di C, perché fa parte di C++ e fa parte di C++, perché non fa parte di C"). Lo stesso vale per il secondo suggerimento su C e OOP.

Quello che personalmente mi piace di C è che mappa piuttosto vicino alla macchina. Spesso è facile vedere come l'output assembler generato dal codice C si relaziona con esso. I nomi dei simboli sono senza fronzoli e possono essere facilmente identificati. La lingua è semplice e minimale. Francamente, non capisco cosa vogliano le persone quando vogliono vedere alcune caratteristiche del C++ incorporate in C: Abbiamo C++, un linguaggio che offre queste cose, con la capacità di scrivere codice efficiente e specifico per piattaforma; perché non usarlo solo?

C11 ha introdotto _Generic, che può essere di interesse per voi.

3

Direi che la ragione prima di tutto C non ha funzione di sovraccarico è che C non mangle nomi di funzione:

Ogni funzione in C è tradotto in un simbolo con lo stesso nome mentre in C++ il nome viene mutilato

Un esempio:

Prendete le funzioni:

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

I nomi dei simboli come straziato dal codice C++ apparirà il seguente:

void foo() = _Z3foov 
void foo(char c) = _Z3fooc 
void foo(int a,int b) = _Z3fooii 

Mentre in codice C questo si tradurrà a:

void foo() = foo 

Linea di fondo - C++ permette nome mangling, in modo che il compilatore "cambiamenti" i nomi delle funzioni e tutti i riferimenti ai tre nomi distinti

C non consente nome mangling al più recente standard (e dubito che questo cambierà mai), in modo da una soluzione del genere non è possibile.

+3

Né lo standard C né lo standard C++ dice nulla sui simboli o il nome di mangling. –

+6

Penso che sia il contrario - C non usa il nome mangling perché non deve supportare l'overloading delle funzioni. – anatolyg

+1

@TC: Questa domanda non riguarda ciò che dicono gli standard (la risposta è semplice: C non ha sovraccarico, perché lo standard lo dice, e C++ lo ha per lo stesso motivo), ma piuttosto perché sono scritti nel modo in cui siamo. Quindi riguarda le implementazioni e la filosofia dietro le lingue; e le implementazioni C++ di solito manipolano i nomi e le implementazioni C no. Ma sono d'accordo con Anatolyg, senza alcune spiegazioni sul perché il nome dei morsi potrebbe non essere desiderato, il ragionamento in questa risposta è circolare. – mafso

8

Si possono trovare un certo punto interessante in C99 rationale 7.22/25 tipo generico matematica <tgmath.h>:

La capacità di sovraccarico intero, così come i tipi galleggianti sarebbe sono stati utili per alcune funzioni, ad esempio copysign. Il sovraccarico di con diversi numeri di argomenti avrebbe consentito il riutilizzo dei nomi, ad esempio remainder per remquo. Tuttavia, queste strutture avrebbero complicato la specifica; e il loro uso coerente naturale, come come un abs galleggiante o un atan a due argomenti, avrebbe introdotto ulteriori incongruenze con C89 per un beneficio insufficiente.

anche C11 standard introdotto tipo _Generic macro, che permette a una sorta di sovraccarico, in senso che diversi tipi possono essere trattati come macro argomenti della funzione simile.

Problemi correlati