C ++ non è adatto per OOP? [chiuso]


12

Ho letto da qualche parte in una delle risposte a una domanda qui (non ricordo quale) che C ++ non è adatto per la programmazione orientata agli oggetti. Si diceva che si potesse usare la sua funzionalità o qualcosa del genere, ma non in senso puramente OOP (in realtà non capivo davvero cosa significasse la persona).

C'è del vero in questo; se è così, perché?



5
OOP non è un termine ben definito, quindi discutere se C ++ sia o non sia adatto è piuttosto inutile.
zvrba,

Risposte:


31

Come descritto in Quindi cosa * Alan Kay intendeva veramente con il termine "orientato agli oggetti"? , Alan Kay pensava che il passaggio di messaggi fosse il bit importante di OOP, ma è il bit che manca a "C con classi" (che in seguito divenne C ++). Il C ++ è solo una struttura con un po 'di comportamento, mentre gli oggetti in Smalltalk o Objective-C sono "intelligenti" in quanto possono decidere cosa fanno con i messaggi inviati. Se un oggetto di tipo Smalltalk riceve un messaggio per il quale non ha un'implementazione, potrebbe pigramente aggiungerne uno, inoltrare il messaggio a un altro oggetto o fare qualsiasi cosa arbitraria.

Ciò che il C ++ offre in termini di orientamento agli oggetti sono i virtualmetodi e il polimorfismo che coinvolgono il modo in cui tali metodi vengono invocati. Quando il compilatore vede un tipo di dati (o class) che ha metodi virtuali, costruisce una vtable con uno slot per ciascun metodo virtuale. Le sottoclassi che implementano i metodi virtuali inseriranno le loro implementazioni negli slot corretti, quindi il codice client deve semplicemente sapere dove nella tabella virtuale cercare il codice da eseguire anziché risolverlo fino alla funzione specifica. Che cosa questo significa è che C ++ in modo efficace ha avere una forma di spedizione multipla, anche se è tutto implementato nel compilatore e non è in grado, come un sistema di Smalltalk-esque.

Se consideri il passaggio dei messaggi fondamentale per OOP, allora mentre puoi farlo con C ++ è tutt'altro che facile. OTOH se si considera OOP per indicare l'associazione di dati con funzioni che agiscono su tali dati, C ++ va bene.


8
+1 - ma ho sempre pensato che una chiamata di funzione fosse comunque un modo ragionevole per passare un messaggio. È vero, è una base di basso livello, piuttosto che una correzione di alto livello per tutto, ma il modello di oggetti attivi mostra che è possibile costruire da quella base.
Steve314,

6
quindi questo vale non solo per C ++, ma per Java, C #, Object Pascal, ecc. E finisce per essere che il sistema di messaggistica API Windows è ciò che Alan intendeva come la cosa più importante in OOP, specialmente il modo in cui è gestito da Delphi
Trinidad,

@trinidad correct, tranne C # in realtà supporta la risoluzione dinamica. Mi aspetto che sia giusto dire che la nostra idea di OOP è cambiata nel tempo per ovviare alla mancanza di messaggi di passaggio. Aiutato senza dubbio dai venditori a dire che la loro tecnologia è decisamente OOP di fronte alle prove ...

@ steve314 sì, lo è. In effetti è così che funziona ObjC, l'invio di un messaggio viene tradotto in una chiamata di funzione che cerca e chiama la funzione metodo. A quanto ho capito, è importante il doppio invio.

1
@Paul: avendo un'esperienza limitata con l'API Win32, non capisco. Qualsiasi API in cui gli oggetti hanno dimensioni variabili e dove è necessario prima chiamare una routine per determinare quanto sarà grande l'oggetto, allocare memoria e richiamarlo, fallisce il mio test per la bellezza.
David Thornley,

27

Questo tipo di discussione mi dà fastidio perché suona come esegesi, persone che discutono sul significato di Holy Scriptute, o sulla Costituzione americana, e su cosa intendessero gli autori originali, come se ciò che pensiamo non contasse.

Guarda, Alan Kay era / è un ragazzo intelligente, e ha avuto una buona idea, che si è scontrato con un sacco di altre buone idee, e ha trovato la sua realizzazione in Smalltalk e in altre lingue.

Non è il Messia e OOP non è l'unico vero paradigma di programmazione.

È una buona idea, tra le tante. Il C ++ contiene buone idee, provenienti dalla mentalità OOP? Certo che lo fa.


8

C ++ supporta OOP, se si definisce OOP per indicare incapsulamento, ereditarietà e polimorfismo.

Tuttavia, C ++ non eccelle davvero in OOP. Uno dei motivi è che il polimorfismo spesso dipende da oggetti allocati in heap, che (nonostante l'uso di puntatori intelligenti), sono più naturali con cui lavorare in un linguaggio raccolto dall'immondizia.

Dove il C ++ eccelle, tuttavia, è nella programmazione generica. C ++ consente di creare facilmente codice generico altamente efficiente attraverso tecniche di programmazione funzionale basate su template.


4

Funzionalità OOP prese in prestito da C ++ da Simula. Uno o più sviluppatori Simula IIRC hanno commentato che C ++ non è quello che avevano in mente.

Il C ++ ha buoni strumenti per l'astrazione, ma è più un linguaggio a paradigma misto che un linguaggio orientato agli oggetti. Le funzionalità orientate agli oggetti ci sono, ma hai delle scelte che non sono "OOP rigorose".

Una delle "opt-out" cattive che si ottengono in C ++ consiste nell'utilizzare i metodi in anticipo piuttosto che in ritardo. Non solo è possibile, ma è l'impostazione predefinita. In Java, "final" è correlato, ma in qualche modo più pulito (specifica l'intento in un modo che non si limita a evitare un sovraccarico di prestazioni banale), e non è il valore predefinito.

In un certo senso, il C ++ mostra segni di essere un esperimento iniziale che è ancora qui. Anche così, è ancora un buon strumento, con molti vantaggi che non si ottengono in altre lingue OOP.


2
C ++ consente non-OOP e C ++ consente OOP, affinché un linguaggio sia OO deve consentire OOP, quindi C ++ è un linguaggio OO.
Trinidad,

1
Credo che Alan Kay, di fama Smalltalk, abbia affermato che il C ++ non era quello che aveva in mente quando ha coniato il termine "orientato agli oggetti". Da quando il C ++ è iniziato come "C with Classes", un innesto di classi Simula su C e non ha mai fatto una pausa netta, non c'è da meravigliarsi che sembri un esperimento iniziale.
David Thornley,

1
@Trinidad: QUALSIASI lingua consente OOP. Ho visto un bel po 'di codice OO nella vecchia e semplice C. Sì, è difficile definire manualmente tutte le tabelle dei metodi virtuali, ma il linguaggio lo consente chiaramente .
Jan Hudec,

4

Forzare tutto per far parte di una classe non produce necessariamente un ottimo codice OO.

Chiedi a un programmatore procedurale inadeguato di programmare in Java e probabilmente prenderanno una classe da qualche parte, gli daranno un metodo statico principale e vi inseriranno 1000 righe di codice. So di averlo visto.

Java ha un'istruzione switch. Ho visto switch( type ) { case typeA: bundles_of_code; break; case typeB: bundles_of_other_code; break }ecc. Sia in codice C ++ che Java.

Il C ++ supporta molti concetti OO ma il suo standard non è definito da esso, tuttavia credo che molto dipenda da quale sia il tuo obiettivo.

Il principale semantico "povero" in C ++ sta permettendo la copia-costruzione di classi in base alle quali un oggetto si trasforma in un altro. Puoi disabilitarlo ma non puoi restituirne uno da una funzione. Fortunatamente questo è risolto in C ++ 0x.


3

OOP non si tratta solo di assicurarsi che tutto rientri o sia in una classe. È perfettamente possibile scrivere codice non OO in un linguaggio "puramente OO". Ad esempio, "main" viene spesso indicato come una funzione globale, ma inventare una classe solo per contenere un metodo statico principale è altrettanto non-OO.

Il C ++ funziona meglio con un mix di varie cose; questo non dovrebbe sorprendere, poiché è così che la maggior parte delle cose buone funzionano meglio. OOP è spesso uno di quegli strumenti molto utili.


2

Il C ++ può essere usato per OOP ma non è "puro" come qualcosa come Smalltalk. Il C ++ ti consente anche di non fare OOP, che è ciò di cui le persone potrebbero parlare.


2

Anche se non sono d'accordo con il sentimento, è vero che il sistema di tipi di C ++ non è OOP puro - non "tutto è un oggetto". I numeri (in particolare) non possono essere estesi tanto facilmente come, ad esempio, in Smalltalk. Ad esempio, non è possibile ridefinire il significato di "2 + 2" (sebbene sia possibile ridefinire il significato di "due + due").

Ma ciò che la maggior parte delle persone probabilmente intende è che molte persone scrivono codice non orientato agli oggetti in C ++ ma credono che, poiché usano un linguaggio "OOP", sono orientate agli oggetti. Non è vero. Ma a mio avviso, puoi scrivere un codice imperativo orribile in Smalltalk e non essere superiore a un design OOP decente in C ++.


1

L'obiezione perfettamente valida di Alan Kay al C ++ era che si trattava di un linguaggio macro in cima a C.

La nozione di "passaggio di messaggi" è semplicemente l'idea che le istanze delle classi siano mantenute in memoria e che espongano metodi che possono essere chiamati. Il passaggio di messaggi è * simulato "in C ++ usando vtables che tengono puntatori a funzioni.

Dire che il passaggio di messaggi non esiste in C ++ non è accurato, ciò che è più preciso da dire è che il passaggio di messaggi è parte integrante di altre lingue come smalltalk e Java perché il linguaggio non sta preelaborando un costrutto estraneo e innestandolo direttamente su C.

Questo è un argomento di progettazione del linguaggio altamente semantico che sospetto sia un po 'oltre il livello di esperienza dell'interrogante.

Detto questo, ci sono mille ragioni per odiare il C ++ e pochissime ragioni per amarlo.

Invece di cercare il martello perfetto e l'unghia perfetta, trova la casa perfetta da costruire e poi trova gli strumenti giusti ... che richiedono esperienza.

È anche importante ricordare che nei sistemi di programmazione ciò che Alan Kay teme non sia "OOP puro" è in realtà un punto di forza del C ++. A ciascuno il suo...


1
Anche l'obiettivo C è iniziato come linguaggio macro sopra C, ma è un linguaggio orientato agli oggetti.
Jan Hudec,

1

A mio avviso, non è tanto un problema di definizione quanto un problema di usabilità.

Gli oggetti sono un'astrazione intesa a facilitare la lettura, la scrittura e la ragione di programmi complessi. Per un programmatore pratico, se un linguaggio soddisfa tutti i criteri di una particolare definizione formale di "orientato agli oggetti" (sembrano essercene diversi concorrenti!) Non è così importante quanto se gli strumenti che offre sono adatti a pensare il tuo programma in termini di detti oggetti, vale a dire effettivamente raccogliere i presunti benefici in termini di produttività di OOP.

In C ++, gli oggetti sono un'astrazione terribilmente traballante , spesso costringendo i programmatori a confrontarsi con problemi sgradevoli legati al modo in cui tali oggetti sono strutturati nella memoria, problemi che ricordano più la codifica in C diretta rispetto ad altri linguaggi OOP. Ad esempio, C ++ Risposte a domande frequenti offre questa critica (tra gli altri):

È molto utile per un professionista acquisire familiarità con i sistemi OO diversi dal C ++ e con definizioni OO diverse dalla trinità "incapsulamento, ereditarietà, polimorfismo" interpretata in modi speciali che consentono al C ++ di essere considerato "OO". Ad esempio, l'affermazione che un ambiente privo di controllo dei confini o di garbage collection non è un ambiente OO sembra scandalosa per le persone abituate al C ++. Ma da molte prospettive, ha molto senso. Se qualcuno può sovrascrivere un oggetto, dov'è "l'incapsulamento"? Se lo smaltimento di un oggetto può comportare riferimenti penzolanti o perdite di memoria, in che modo il sistema è "orientato agli oggetti" ? Che dire della capacità di dire che tipo di oggetto si trova in un determinato luogo e tempo? Dici che il software funziona con gli oggetti - dove sono? E se non si riesce a scoprirlo, come si può eseguire il debug del software?

Il C ++ è orientato agli oggetti, ma in modo spiacevole e incompleto: i suoi utenti devono impegnarsi molto per assicurarsi che i loro dati si comportino effettivamente come oggetti "reali" anziché bit erranti. Detto questo, un sacco di codice è stato scritto in C ++ per tutta la sua durata, la maggior parte di essi fa uso di classi e invio dinamico, quindi è evidentemente qualcosa che puoi usare per OOP pratico.


-1 per fare riferimento all'FQA in quella che dovrebbe essere una risposta seria. L'FQA è un nido di distorsioni, mezze verità e incomprensioni.
David Thornley,

@DavidThornley La citazione particolare è una distorsione, una mezza verità o un malinteso?
Alex P

Da qualche parte lì dentro. L'affermazione secondo cui un linguaggio OO deve avere il controllo dei confini (a volte incorporato comunque in contenitori standard C ++) e la garbage collection (i puntatori intelligenti sono la garbage collection primitiva) è forzata e disingenua. La frase su un linguaggio che consente ai riferimenti penzolanti di non essere orientati agli oggetti è chiaramente Proof of Assertion Blatant. Sono perplesso dalla "capacità di dire che tipo di oggetto"; il tipo di puntatore lo restituisce per oggetti senza comportamento virtuale e RTTI lo gestisce per oggetti con comportamento virtuale.
David Thornley,

@DavidThornley L'affermazione della FQA è che un linguaggio OO utile dovrebbe avere queste cose - che è in linea con la domanda posta (il C ++ è "adatto"?). Penso che un'affermazione sulle definizioni di bare-bones non risolva davvero questo ... "Capacità di dire": un comportamento di errore comune che accede a un oggetto che non è realmente lì, seguendo un puntatore ad alcuni dati non inizializzati o precedentemente sovrascritti; e il tuo programma prenderà felicemente quell'immondizia e lo interpreterà come dati, quindi seguirà i puntatori di immondizia verso altri dati di immondizia fino a quando non raggiunge un indirizzo fuori limite o si verifica un errore grave.
Alex P

Tuttavia, la citazione almeno suggeriva fortemente l'affermazione che una lingua senza controllo dei confini o garbage collection non fosse OO, e ignorava il fatto che hai quelle cose in C ++ se vuoi. La questione se una lingua previene determinate classi di errori o meno (per qualsiasi motivo) è ortogonale al fatto che sia OO.
David Thornley,

-1

C'è una ragione per cui Graham Lee ha avuto il maggior numero di voti qui. Per ribadire, sembra che una classe C ++ non sia realmente un oggetto, nel senso che non esegue il passaggio di messaggi. Penso che questo sia ciò che incanta molto le persone quando stanno imparando il C ++ o oop. Alle persone viene detto che "orientato agli oggetti" è "questo" e quindi viene detto che C ++ lo fa diversamente. Bene, C ++ non ha mai fatto OOP in modo diverso. Se la pensi in questo modo non apprezzerai mai le classi C ++ per quello per cui sono pensate e cioè che sono semplicemente un miglioramento del paradigma procedurale incorporando l'astrazione e il comportamento dinamico. Quindi le classi C ++ sono fondamentalmente procedurali, migliorano semplicemente il paradigma procedurale, o meglio sono una versione più avanzata di una struttura C.


Hai dei veri motivi a sostegno delle tue argomentazioni? Sembra che tu stia facendo affermazioni e affermando che coloro che non sono d'accordo devono sbagliarsi, o cambieranno idea se la guardassero diversamente, o forse se condividessero la tua esatta definizione di OO.
David Thornley,

Giusto. Puoi leggere questo articolo . Immagino che ciò che stavo dicendo sia che c ++ non è "programmazione orientata agli oggetti" nel senso stretto di Alan Kay. Tuttavia, se si definisce OOP come una struttura di dati con comportamento, è possibile considerare c ++ come OOP. Nella mia mente, però, è più preciso vedere una classe c ++ come un'astrazione di programmazione procedurale di livello superiore. Una classe c ++ è molto più efficiente di un oggetto in stile Kay, ma peggio per la concorrenza. Personalmente penso che la classe c ++ sia un ottimo design.
annoying_squid il

1
Grazie per il link, ma spiega solo cosa intendeva Alan Kay. Inoltre, non sono d'accordo sul fatto che Smalltalk sia generalmente considerato la prima lingua OO, e Wikipedia concorda con me sul fatto che quella era Simula, una delle due lingue Stroustrup combinata per formare C con Classi. Sono interessato alla tua affermazione che una classe C ++ è più un'astrazione di programmazione procedurale di livello superiore rispetto a un modello di oggetto, ma ancora non capisco perché la pensi così.
David Thornley,

L'orientamento agli oggetti è probabilmente un termine soggettivo, se possiamo essere d'accordo su questo. Ma vedo un oggetto Kay come un modo più naturale per disaccoppiare il codice e introdurre una modularità concorrente, nel senso che ogni oggetto svolge un ruolo come mini-computer che interagiscono attraverso il passaggio dei messaggi. In base a questo modello, ci deve essere poco o nessun codice 'tra' b / c, l'intera logica del programma può essere espressa come celle e messaggi. In confronto, l'uso di "classi" richiede in genere un codice di colla procedurale in mezzo (manca una vera modularità) ma il vantaggio è che le classi sono molto più efficienti.
annoying_squid l'

-1

Steve Yegge l'ha detto meglio :

Il C ++ è il linguaggio più stupido della terra, nel vero senso di essere il meno senziente. Non conosce se stesso.

Il sistema di oggetti in C ++ è così cablato e risolto in fase di compilazione, che è molto distante dalla nozione originale di OOP che implica tra l'altro passaggio di messaggi, introspezione, riflessione, invio dinamico e associazione tardiva. L'unica cosa che C ++ e Smalltalk hanno in comune sono un po 'di vocabolario.


In che modo il C ++ è il linguaggio meno senziente? Cosa significa che una lingua è senziente? Se vuoi dire che manca di capacità di riflessione, è abbastanza comune e certamente non sceglie C ++ da una folla.
David Thornley,

2
Come diavolo potresti dire che l'ha detto "migliore"? Non ho idea di cosa significhi quella citazione casuale.
user16764

+1 dicendo che questo genere di cose otterrà un sacco di difetti dai basher di C ++, ma va detto - non puoi davvero OOP senza riflessione, perché non hai i generici per occuparti di cose orizzontali ( aspetti) - ciclo di vita (attivazione, eliminazione), gestione generica degli errori, proxy generico, serializzazione generica, parallelismo di compiti generici - finiscono per inquinare il codice e rompere il SoC.
vski,

Grazie. Non riesco a credere di essere arrivato a -3 per dire che un linguaggio senza riflessione non è un buon esempio di OOP.
John Cromartie,

1
@JohnCromartie, potresti approfondire questo punto nella tua risposta?
Jeremy Heiler,
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.