Perché C non è considerato un linguaggio "orientato agli oggetti"?


92

Sembra che C abbia i suoi quasi-oggetti come 'struct' che possono essere considerati come oggetti (nel modo di alto livello che normalmente penseremmo).

Inoltre, i file C stessi sono sostanzialmente "moduli" separati, giusto? Quindi i moduli non sono simili agli "oggetti"? Sono confuso sul perché C, che sembra così simile al C ++, è considerato un linguaggio "procedurale" di basso livello in cui il C ++ è "orientato agli oggetti" di alto livello

* modifica: (chiarimento) perché e dove, viene tracciata la linea, per che cos'è un 'oggetto', e non lo è?


40
Tutti - perché i voti negativi? È una domanda di base ma non è una cattiva.
Jon Hopkins,

7
Puoi usare i principi OO in modo efficace in C (e le persone che scrivono un buon codice C in genere lo fanno), ma il linguaggio non è costruito attorno a renderlo facile, come molte altre lingue recenti.
asveikau,

5
C ha semplicemente un approccio diverso, più semplice e (a dire il vero) meglio definito (almeno tra la comunità open source) all'astrazione dei dati. Il C ++ tende ad essere un motore di astrazione e consente molte cose fantastiche, ma comporta il costo di dover capire come [non] usarle correttamente, cosa che, molto spesso, è del tutto assente nei programmi comuni. Vedi la mia risposta completa per maggiori dettagli.
Yam Marcovic,

1
In breve: le strutture non possono avere metodi. (Il puntatore a una funzione non lo taglia del tutto).
SF.

1
È possibile eseguire una programmazione basata su oggetti in C, con qualche difficoltà. Ma ciò non lo rende orientato agli oggetti .
Wedge

Risposte:


101

Sembra che C abbia i suoi quasi-oggetti come "struct" che possono essere considerati come oggetti

Insieme, leggiamo la pagina Wikipedia sulla programmazione orientata agli oggetti e controlliamo le caratteristiche delle strutture in stile C che corrispondono a quello che è tradizionalmente considerato stile orientato agli oggetti:

(OOP) è un paradigma di programmazione che utilizza "oggetti" - strutture di dati costituite da campi e metodi di dati insieme alle loro interazioni

Le strutture C sono costituite da campi e metodi insieme alle loro interazioni ? No.

Le tecniche di programmazione possono includere caratteristiche come l'astrazione dei dati, l'incapsulamento, la messaggistica, la modularità, il polimorfismo e l'ereditarietà.

Le strutture C fanno una di queste cose in un modo "di prima classe"? No. La lingua funziona contro di te ad ogni passo.

l'approccio orientato agli oggetti incoraggia il programmatore a posizionare i dati dove non sono direttamente accessibili dal resto del programma

Le strutture C fanno questo? No.

Un programma orientato agli oggetti di solito conterrà diversi tipi di oggetti, ogni tipo corrispondente a un particolare tipo di dati complessi da gestire o forse a un oggetto o concetto del mondo reale

Le strutture C fanno questo? Sì.

Gli oggetti possono essere considerati come un avvolgimento dei loro dati all'interno di un insieme di funzioni progettate per garantire che i dati vengano utilizzati in modo appropriato

No.

ogni oggetto è in grado di ricevere messaggi, elaborare dati e inviare messaggi ad altri oggetti

Una stessa struttura può inviare e ricevere messaggi? No. Può elaborare i dati? No.

Le strutture di dati OOP tendono a "portare con sé i propri operatori"

Questo succede in C? No.

Invio dinamico ... Incapsulamento ... Polimorfismo dei sottotipi ... Eredità degli oggetti ... Ricorsione aperta ... Classi di oggetti ... Istanze di classi ... Metodi che agiscono sugli oggetti collegati ... Passaggio di messaggi ... Astrazione

C'è una di queste caratteristiche delle strutture C? No.

Quali caratteristiche delle strutture pensi siano "orientate agli oggetti"? Perché non riesco a trovare alcuna altra parte il fatto che le strutture definiscono i tipi .

Ora, ovviamente, puoi creare strutture che hanno campi che sono puntatori a funzioni. È possibile fare in modo che le strutture abbiano campi che sono puntatori a matrici di puntatori a funzione, corrispondenti a tabelle di metodi virtuali. E così via. Ovviamente puoi emulare C ++ in C. Ma questo è un modo molto non idiomatico di programmare in C; staresti meglio usando solo C ++.

Inoltre, i file C stessi sono sostanzialmente "moduli" separati, giusto? Quindi i moduli non sono simili agli "oggetti"?

Ancora una volta, quali caratteristiche dei moduli stai pensando che li fanno agire come oggetti? I moduli supportano l'astrazione, l'incapsulamento, la messaggistica, la modularità, il polimorfismo e l'ereditarietà?

L'astrazione e l'incapsulamento sono piuttosto deboli. Ovviamente i moduli sono modulari; ecco perché si chiamano moduli. Messaging? Solo nel senso che una chiamata di metodo è un messaggio e i moduli possono contenere metodi. Polimorfismo? No. Eredità? No. I moduli sono candidati piuttosto deboli per "oggetti".


15
Non sono d'accordo sul fatto che "emulare C ++" (il tuo termine) non sia idiomatico C. Un contro esempio potrebbe essere il modo in cui un kernel del sistema operativo implementa in genere le operazioni sui file - prendi Linux come esempio, dove hai strutture piene di puntatori a funzioni. Possono essere in qualche modo idiomi "specifici del dominio" (limitati alla scrittura di driver su * nix, diciamo), ma sono riconoscibili e svolgono il lavoro in modo abbastanza pulito per alcuni scopi. Ci sono anche alcuni esempi di librerie in modalità utente che fanno abbastanza bene l'idea di OO; prendi Gtk + e le librerie da cui dipende. Chiamalo hacky e potresti avere ragione, ma questi non sono terribili con cui lavorare
asveikau

5
@asveikau: L'idea che una pratica sia insolita (anche se non inaudita) e "hacky" non significa che, per definizione, non sia idiomatica?
Adam Robinson,

19
@asveikau: Certo, ci sono cose che puoi fare per rendere i programmi C più OO in grande stile. Ma come dici tu, richiede disciplina per farlo; le caratteristiche del linguaggio stesso non ti guidano naturalmente verso l'incapsulamento, il polimorfismo, l'eredità di classe e così via. Piuttosto, lo sviluppatore può imporre quel modello sulla lingua. Ciò non significa che le strutture siano logicamente le stesse cose degli oggetti. Diamine, puoi programmare in uno stile OO anche in Lisp, ma ciò non significa che le celle contro siano oggetti.
Eric Lippert,

3
@asveikau, posso suggerire che la tua (errata) interpretazione di "idioma" come "di te stesso" è leggermente ... idiosincratica? :)
Benjol,

8
@BillK: le strutture non possono contenere codice in C. Le strutture possono contenere puntatori a funzioni , che sono dati . I puntatori a funzione non sono codice . Il codice è un artefatto testuale creato da un programmatore.
Eric Lippert,

46

La parola chiave è "orientata", non "oggetto". Anche il codice C ++ che utilizza oggetti ma li utilizza come struct non è orientato agli oggetti .

C e C ++ possono entrambi fare OOP (a parte il controllo dell'accesso in C), ma la sintassi per farlo in C è scomoda (per non dire altro), mentre la sintassi in C ++ lo rende molto invitante. Il C è orientato al procedurale, mentre il C ++ è orientato agli oggetti, nonostante le capacità di base quasi identiche al riguardo.

Il codice che utilizza oggetti per implementare progetti che possono essere eseguiti solo con oggetti (di solito significa sfruttare il polimorfismo) è un codice orientato agli oggetti. Il codice che utilizza oggetti poco più che sacchi di dati, anche utilizzando l'ereditarietà in un linguaggio orientato agli oggetti, è in realtà solo un codice procedurale più complicato di quanto non debba essere. Il codice in C che utilizza i puntatori a funzione che vengono cambiati in fase di esecuzione con strutture piene di dati fa un po 'il polimorfismo e si potrebbe dire che sia "orientato agli oggetti", anche in un linguaggio proceduralmente orientato.


2
+1 Per indicare la nostra C può essere OO. Non è conveniente, ma può essere fatto.
dietbuddha,

Creare oggetti in VBA è più semplice, ma non lo considero neanche orientato agli oggetti.
JeffO,

VBA chiamo "basato sull'oggetto". Usa gli oggetti, ma non polimorficamente, e nel poco lavoro che ho fatto al suo interno, non sono sicuro che tu possa persino fare il polimorfismo, indipendentemente dal tipo di codice acrobatico che provi. Fondamentalmente è un linguaggio procedurale con incapsulamento.
kylben,

2
La maggior parte delle lingue può agire come OO, funzionale o praticamente qualsiasi stile di linguaggio. la differenza è "Orientato" e non l'avevo mai sentito dire così. Vorrei poter votare 3 volte e accettarlo, è la risposta giusta.
Bill K,

1
@kylben Non sarebbe troppo lungo archiviare il codice SQL nella tabella, quindi estrarre ed eseguire (rendendo la tabella l'oggetto) Sarebbe un esperimento interessante. In realtà è un po 'allettante ...
Bill K,

19

Basato sui principi di altissimo livello:

Un oggetto è un incapsulamento di dati e comportamenti in modo interconnesso in modo tale da funzionare nel suo insieme che può essere istanziato più volte e lavorato come una scatola nera se si conosce l'interfaccia esterna.

Le strutture contengono dati ma nessun comportamento e pertanto non possono essere considerati oggetti.

I moduli contengono sia comportamento che dati ma non sono incapsulati in modo tale che i due siano correlati e certamente non possono essere istanziati più volte.

E questo prima di entrare in eredità e polimorfismo ...


Come mai comportamento e dati nei moduli non sono correlati? Le funzioni membro non sono fondamentalmente il "comportamento" sui dati esistenti all'interno del modulo?
Templare oscuro,

4
Il problema è che non sono incapsulati, non che non sono correlati.
Eoin Carroll,

In realtà gli oggetti sono centrati principalmente sul comportamento , non sui dati. I dati sono / dovrebbero essere cittadini di seconda classe in OOP. Le strutture, invece, sono incentrate sui dati e non hanno alcun comportamento.
Sklivvz,

1
@ Dark Templar - Cosa ha detto Eoin ... È nella natura della relazione. Posso vedere da dove vieni - potresti certamente usare Struct all'interno di un modulo in modo tale da emulare alcuni elementi molto basilari di OO ma gran parte di ciò che faresti farebbe affidamento sul programmatore che si attacca a un set di regole autoimposte anziché far applicare la lingua. E perché dovresti preoccuparti? Non stai ottenendo nessuno dei vantaggi di OO - nessuna eredità per esempio - e ti stai limitando.
Jon Hopkins,

Questa è una risposta migliore di quella contrassegnata come corretta.
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

6

"le strutture" sono solo dati. Il solito test rapido e sporco dell '"orientamento dell'oggetto" è: "Esiste una struttura che consente di incapsulare codice e dati come una singola unità?". C non ci riesce ed è quindi procedurale. C ++ supera quel test.


6
Esistono soluzioni alternative, le strutture possono avere puntatori di funzioni statiche alle funzioni membro. Avranno bisogno di un thispuntatore esplicito , ma in tal caso, i dati e i mezzi per elaborare i dati verranno incapsulati all'interno della struttura.
Coder

@Brian Knoblauch: ma non è un file C in sé un incapsulamento di dati e codice ??
Templare oscuro,

@DarkTemplar In un certo senso, sì, ma a meno che non riesca a creare unità di traduzione, compilarle e caricarle nel processo in esecuzione in fase di esecuzione, questo è un piccolo vantaggio.

unità di traduzione? >. <
Templare oscuro,

@Dark Templar: un'unità di traduzione è un file sorgente più niente #included in essa, e meno qualsiasi cosa rimosso da non essere condizionale incluso ( #if, #ifdef, e simili).
David Thornley,

5

C, proprio come C ++, ha la capacità di fornire Data Abstraction , che è un idioma del paradigma di programmazione orientata agli oggetti che esisteva prima di esso.

  • Le strutture C possono avere dati (e questo è il loro scopo principale)
  • Le strutture C possono anche definire i puntatori a funzioni come dati
  • Le strutture C possono e spesso hanno un insieme di funzioni associate, proprio come i metodi, solo questo puntatore non viene passato implicitamente, ma è necessario specificarlo esplicitamente come primo argomento di ciascun metodo progettato per gestire la struttura specificata. C ++ lo fa automaticamente per te, sia quando definisci che chiami i metodi class / struct.

OOP in C ++ estende i mezzi per estrarre i dati. Alcuni dicono che è dannoso , mentre altri lo considerano un buon strumento se usato correttamente.

  • Il C ++ rende implicito questo puntatore non richiedendo all'utente di passarlo in "metodi della classe / struttura" purché il tipo possa essere (almeno in parte) identificato.
  • C ++ consente di limitare l'accesso a determinati metodi (funzioni di classe), e quindi consente una "programmazione difensiva" o "a prova di idiota".
  • Il C ++ incoraggia le astrazioni fornendo una maggiore sicurezza del tipo introducendo
    1. Il nuovo operatore invece di malloc + cast
    2. Modelli anziché puntatori vuoti
    3. Funzioni incorporate che ricevono valori digitati anziché macro
    4. Costruito nel polimorfismo che non devi implementare da solo, che ti consente di creare gerarchie , contratti e specializzazioni di astrazione .

Tuttavia, troverai molti "hacker" che predicano per capire come C sia perfettamente in grado di produrre la giusta quantità di astrazione e in che modo il sovraccarico creato da C ++ li distragga dal risolvere il problema reale.

Inefficienti modelli di programmazione astratti in cui due anni dopo noterai che alcune astrazioni non erano molto efficienti, ma ora tutto il tuo codice dipende da tutti i bei modelli di oggetti che lo circondano e non puoi correggerlo senza riscrivere la tua app. - Linus Torvalds

Altri tendono a guardarlo in modo più equilibrato, accettando sia i vantaggi che gli svantaggi.

C rende facile spararsi al piede; Il C ++ lo rende più difficile, ma quando lo fai ti fa saltare tutta la gamba. - Bjarne Stroustrup


2

Devi guardare l'altro lato della medaglia: C ++.

In OOP, pensiamo a un oggetto astratto (e progettiamo il programma di conseguenza), ad esempio un'auto che può fermarsi, accelerare, girare a sinistra o a destra, ecc. Una struttura con un fascio di funzioni semplicemente non si adatta al concetto.

Con oggetti "reali", ad esempio, dobbiamo nascondere i membri, oppure possiamo anche avere l'eredità con una relazione "è una" reale e molte altre.

DOPO LA LETTURA DEI COMMENTI SOTTO: Beh, è ​​giusto che (quasi) tutto possa essere fatto con C (questo è sempre vero), ma a prima vista ho pensato che ciò che separa c da c ++ è il modo in cui pensi quando si progetta un programma.

L'unica cosa che fa davvero la differenza è l'imposizione di politiche da parte del compilatore . cioè pura funzione virtuale, e simili. ma questa risposta riguarderà solo problemi tecnici, ma penso che la differenza principale (come detto) sia il modo originale in cui pensi mentre scrivi il codice, dato che C ++ ti offre una sintassi meglio integrata per fare queste cose, invece di fare OOP in un modo un po 'goffo in C.


Non sei davvero sicuro del perché una struttura con un "pacchetto di funzioni" non rientri nel concetto? +1 per la risposta, però
Templare oscuro,

1
A parte il controllo degli accessi (privato / protetto / pubblico) tutto il resto può essere fatto con le strutture.
Coder

1
@DarkTemplar: Beh, puoi provare a emulare OOP in C (le persone hanno effettivamente scritto ebook su quell'argomento e farlo nel mondo reale, anche se molto raramente), come puoi provare ad emulare la programmazione funzionale in Java. Ma C non fornisce alcun aiuto, quindi C il linguaggio non è orientato agli oggetti .

1

L'hai detto tu stesso. Mentre C ha cose che sono simili a oggetti, non sono ancora oggetti, ed è per questo che C non è considerato un linguaggio OOP.


1
Bene, immagino che la domanda sia: perché e dove viene tracciata la linea per ciò che è un oggetto e cosa non lo è?
Templare oscuro,

1

Orientato agli oggetti si riferisce sia a un modello architettonico (o anche a un meta-modello), sia ai linguaggi che dispongono di funzioni che aiutano a implementare o imporre questo modello.

Puoi implementare un design "OO" (il desktop di Gnome è forse il miglior esempio di OO fatto in puro C), l'ho visto persino fatto con COBOL!

Tuttavia, essere in grado di implementare una dose di design OO non rende il linguaggio OO. I puristi sostengono che Java e C ++ non sono veramente OO in quanto non è possibile ignorare o ereditare i "tipi" di base come "int" e "char" e Java non supporta l'ereditarietà multipla. Ma poiché sono i linguaggi OO più utilizzati e supportano la maggior parte dei paradigmi più "veri" programmatori che vengono pagati per produrre codice funzionante li considerano i linguaggi OO.

C d'altra parte supporta solo le strutture (come COBOL, Pascal e dozzine di altri linguaggi procedurali), si potrebbe sostenere che supporta l'ereditarietà multipla in quanto è possibile utilizzare qualsiasi funzione su qualsiasi pezzo di dati, ma la maggior parte lo considererebbe un bug piuttosto di una caratteristica.


0

Diamo un'occhiata alla definizione di OO:

  • messaggistica
  • incapsulamento
  • Rilegatura tardiva

C non fornisce nessuno di questi tre. In particolare, non fornisce la messaggistica , che è la più importante.


1
Penso che non dovrei essere d'accordo. Sicuramente puoi avere messaggi in C - lavora con le API dell'obiettivo C di C e lo scopri in profondità - e l'associazione tardiva può essere fatta attraverso i puntatori a funzione, ma non ottieni molto zucchero sintattico per nasconderlo. (L'incapsulamento in realtà è facile in C; i puntatori a tipi di struttura incompleti fanno perfettamente il lavoro.)
Donal Fellows

Anche l'ereditarietà è considerata importante in OO e C non lo fa. La cosa più vicina all'incapsulamento in C sono file separati che possono avere staticfunzioni interne ( ) e membri di dati.
David Thornley,

@DonalFellows, il messaggio effettivo che passa in Objective-C potrebbe essere facilmente implementato come una macro C99. L'unica cosa che il compilatore ha da fare è che genera staticamente tutte le strutture necessarie da poche righe di codice di alto livello. La maggior parte se non tutte le funzionalità sono disponibili dall'API C.
qpr,

0

Ci sono un certo numero di ingredienti chiave in OO, ma i grandi sono che la maggior parte del codice non sa cosa c'è dentro un oggetto (vedono l'interfaccia di superficie, non l'implementazione), che lo stato di un oggetto è un'unità gestita (vale a dire, quando l'oggetto cessa di essere, così fa il suo stato), e quando un codice invoca un'operazione su un oggetto, lo fanno senza sapere esattamente cosa sia o coinvolga quell'operazione (tutto ciò che fanno è seguire uno schema per lanciare un "Messaggio" oltre il muro).

C fa bene l'incapsulamento; il codice che non vede la definizione di una struttura non può (legittimamente) sbirciare al suo interno. Tutto quello che devi fare è inserire una definizione come questa in un file di intestazione:

struct FooImpl;
typedef struct FooImpl *Foo;

Naturalmente, ci sarà la necessità di una funzione che costruisce Foos (cioè una fabbrica) e che dovrebbe delegare parte del lavoro all'oggetto allocato stesso (cioè, attraverso un metodo "costruttore"), e anche avere un modo di smaltire di nuovo l'oggetto (pur lasciandolo ripulire con il suo metodo "distruttore") ma sono dettagli.

Il dispacciamento di metodo (cioè la messaggistica) può anche essere fatto attraverso la convenzione che il primo elemento della struttura è in realtà un puntatore a una struttura piena di puntatori a funzione e che ciascuno di quei puntatori a funzione deve prendere Foocome primo argomento. La spedizione diventa quindi una questione di cercare la funzione e chiamarla con l'argomento giusto riscrivere, che non è così difficile da fare con una macro e un po 'astuta. (Quella tabella di funzioni è il nucleo di ciò che una classe è realmente in un linguaggio come C ++.)

Inoltre, questo ti dà anche un'associazione tardiva: tutto il codice di spedizione sa che sta invocando un offset particolare in una tabella puntata dall'oggetto. Ciò deve essere impostato solo durante l'allocazione e l'inizializzazione dell'oggetto. È possibile optare per schemi di spedizione ancora più complessi che ti offrono più dinamismo di runtime (a un costo di velocità) ma sono ciliegie in cima al meccanismo di base.

Tuttavia ciò non significa che C sia un linguaggio OO. La chiave è che C ti lascia fare tutto il lavoro complicato di scrivere le convenzioni e il meccanismo di invio (o utilizzare una libreria di terze parti). È molto lavoro. Inoltre non fornisce supporto sintattico o semantico, quindi implementare un sistema di classe completa (con cose come l'eredità) sarebbe inutilmente doloroso; se hai a che fare con un problema complesso che è ben descritto da un modello OO, un linguaggio OO sarà molto utile per scrivere la soluzione. L'ulteriore complessità può essere giustificata.


0

Penso che C sia perfettamente perfetto e decente per l'implementazione di concetti orientati agli oggetti, scrollata di spalle . La maggior parte delle differenze, a mio avviso, tra il sottoinsieme denominatore comune delle lingue considerate orientate agli oggetti sono minori e di natura sintattica dal mio punto di vista pragmatico.

Cominciamo con, diciamo, nascondere le informazioni. In C possiamo raggiungere questo obiettivo semplicemente nascondendo la definizione di una struttura e lavorando con essa attraverso puntatori opachi. Ciò modella efficacemente la distinzione publicvs. privatedei campi di dati man mano che arriviamo alle classi. Ed è abbastanza facile da fare e difficilmente anti-idiomatico, poiché la libreria C standard fa molto affidamento su questo per ottenere il nascondimento delle informazioni.

Naturalmente perdi la capacità di controllare facilmente esattamente dove la struttura è allocata in memoria usando tipi opachi, ma questa è solo una notevole differenza tra, diciamo, C e C ++. C ++ è sicuramente uno strumento superiore quando si confronta la sua capacità di programmare concetti orientati agli oggetti su C pur mantenendo il controllo sui layout di memoria, ma ciò non significa necessariamente che Java o C # sia superiore a C in questo senso, dal momento che quei due ti rendono perde completamente la capacità di controllare dove gli oggetti sono allocati in memoria.

E dobbiamo usare una sintassi come fopen(file, ...); fclose(file);al contrario di file.open(...); file.close();ma whoop grande. A chi importa davvero? Forse solo qualcuno che si appoggia pesantemente al completamento automatico nel proprio IDE. Devo ammettere che può essere una funzione molto utile dal punto di vista pratico, ma forse non uno che richiede una discussione sull'opportunità di un linguaggio adatto a OOP.

Ci manca la capacità di implementare efficacemente i protectedcampi. Ti invierò totalmente lì. Ma non credo che ci sia una regola concreta che dice: " Tutte le lingue OO dovrebbero avere una funzione che consenta alle sottoclassi di accedere ai membri di una classe base a cui i normali client non dovrebbero ancora accedere ." Inoltre, raramente vedo casi d'uso per membri protetti che non sono almeno un po 'sospetti di diventare un ostacolo alla manutenzione.

E, naturalmente, dobbiamo "emulare" il polimorfismo OO con tabelle di puntatori di funzioni e puntatori a loro per un invio dinamico con un po 'più di piastra per inizializzare quelli analogici vtablese vptrs, ma un po' di piastra di caldaia non mi ha mai causato molto dolore.

L'ereditarietà è molto simile. Possiamo facilmente modellarlo attraverso la composizione e ai meccanismi interni dei compilatori si riduce alla stessa cosa. Naturalmente perdiamo la sicurezza dei tipi se vogliamo effettuare il downcast , e lì direi se si desidera effettuare il downcasting , per favore non usare C per questo perché le cose che le persone fanno in C per emulare il downcasting possono essere orribili da un tipo punto di vista della sicurezza, ma preferirei che le persone non si abbattessero affatto. La sicurezza dei tipi è qualcosa che puoi facilmente perdere in C poiché il compilatore offre così tanto margine di manovra per interpretare le cose come solo bit e byte, sacrificando la capacità di catturare potenziali errori in fase di compilazione, ma alcuni linguaggi considerati non sono orientati agli oggetti anche staticamente digitata.

Quindi non lo so, penso che vada bene. Ovviamente non userei C per cercare di creare una base di codice su larga scala conforme ai principi SOLIDI, ma non è necessariamente dovuta alle sue carenze nel fronte orientato agli oggetti. Molte delle funzionalità che mi mancherebbero se tentassi di usare C per tale scopo sarebbero legate a funzionalità linguistiche non direttamente considerate un prerequisito per OOP come sicurezza di tipo forte, distruttori che vengono automaticamente invocati quando gli oggetti escono dall'ambito, operatore sovraccarico, modelli / generici e gestione delle eccezioni. È quando mi mancano quelle funzionalità accessorie che raggiungo per C ++.


1
Non sono sicuro di come i costruttori non possano essere considerati un prerequisito per OOP. Parte dell'essenza di base dell'incapsulamento è la capacità di assicurare invarianti per un oggetto. E ciò richiede la capacità di inizializzare correttamente l'oggetto all'interno di quegli invarianti. Ciò richiede un costruttore: una o più funzioni, in modo che non si possa dire che l'oggetto esiste ancora fino a quando almeno una di esse è stata chiamata.
Nicol Bolas,

Quando abbiamo informazioni nascoste con tipi opachi, l'unico modo per istanziarle, copiarle / clonarle e distruggerle è attraverso l'equivalente analogico di funzioni che fungono da costruttori e distruttori con la stessa capacità di mantenere quegli invarianti. E 'solo non direttamente modellata nella lingua e potrebbe assomigliare la forma di foo_createe foo_destroye foo_clone, ad esempio

Tutto ciò di cui abbiamo bisogno per mantenere invarianti struct Fooin questo caso è assicurarci che i suoi dati non possano essere accessibili e mutati dal mondo esterno, che i tipi opachi (dichiarati ma non definiti al mondo esterno) danno subito. È probabilmente una forma più forte di nascondere le informazioni, alla pari di quella di un pimplin C ++.

Sì, so come le persone implementano OOP in C, grazie. Il mio punto era che la tua affermazione che i costruttori "non sono direttamente considerati un prerequisito per OOP" è in errore.
Nicol Bolas,

Vedo, lasciami corretto che ... ma in quel caso potremmo dire che C fornisce (adeguato?) Supporto a distruttori e costruttori?

-1

Non è una cattiva domanda.

Se hai intenzione di chiamare c una lingua OO, dovrai chiamare anche quasi tutte le lingue procedurali OO. Quindi renderebbe il termine insignificante. c non ha supporto linguistico per OO. Se ha le strutture, ma le strutture typesnon sono classi.

In realtà c non ha molte funzionalità rispetto alla maggior parte delle lingue. È utilizzato principalmente per la sua velocità, semplicità, popolarità e supporto tra cui tonnellate di librerie.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.