Il linguaggio C++ fornisce le funzioni virtual
. Entro i limiti di una pura implementazione del linguaggio C, come si può ottenere un effetto simile?Come si può implementare le funzioni virtuali C++ in C
risposta
Stolen da here.
Dalla classe
class A {
protected:
int a;
public:
A() {a = 10;}
virtual void update() {a++;}
int access() {update(); return a;}
};
un codice C++ frammento C può essere derivata. Le tre funzioni membro C++ di class A
vengono riscritte utilizzando il codice non in linea (autonomo) e raccolte per indirizzo in una struttura denominata A_functable
. I membri dati di A
e combinati con la tabella delle funzioni in una struttura C denominata A
.
struct A;
typedef struct {
void (*A)(struct A*);
void (*update)(struct A*);
int (*access)(struct A*);
} A_functable;
typedef struct A{
int a;
A_functable *vmt;
} A;
void A_A(A *this);
void A_update(A* this);
int A_access(A* this);
A_functable A_vmt = {A_A, A_update, A_access};
void A_A(A *this) {this->vmt = &A_vmt; this->a = 10;}
void A_update(A* this) {this->a++;}
int A_access(A* this) {this->vmt->update(this); return this->a;}
/*
class B: public A {
public:
void update() {a--;}
};
*/
struct B;
typedef struct {
void (*B)(struct B*);
void (*update)(struct B*);
int (*access)(struct A*);
} B_functable;
typedef struct B {
A inherited;
} B;
void B_B(B *this);
void B_update(B* this);
B_functable B_vmt = {B_B, B_update, A_access};
void B_B(B *this) {A_A(this); this->inherited.vmt = &B_vmt; }
void B_update(B* this) {this->inherited.a--;}
int B_access(B* this) {this->inherited.vmt->update(this); return this->inherited.a;}
int main() {
A x;
B y;
A_A(&x);
B_B(&y);
printf("%d\n", x.vmt->access(&x));
printf("%d\n", y.inherited.vmt->access(&y));
}
Più elaborato del necessario, ma ottiene il punto attraverso.
+1 Grande esempio: si tratta del più vicino possibile alla traduzione di vtables in C ed è molto più elegante dei programmatori C che fanno cose come i cast dei puntatori di funzione o le strutture di casting dei puntatori di funzione. È ancora ingombrante e imbarazzante, ma hey, C non è stato progettato per questo. – stinky472
@ stinky472: Sono d'accordo con te, ma quando qualcuno è sul punto di aver bisogno di codice come questo, non ha senso. Alcune lingue sono più adatte a determinati problemi. – Alerty
Verissimo, ma sono stato costretto a lavorare nei sistemi C cercando di implementare OOP. Lo hanno fatto lanciando le strutture con i puntatori di funzione (come la struttura di cast A), piuttosto che il passaggio di A per il polimorfismo e consentendo a ogni struct di sottoclasse di memorizzare semplicemente A e assegnare ad esso indirizzi e dati di funzione appropriati. Questo, perlomeno, è molto più elegante di un cast di struct casting o di casting. – stinky472
Here è una descrizione delle funzioni virtuali.
Non esiste alcun modo per implementare le funzioni virtuali in C semplice, perché C non ha alcuna nozione di ereditarietà.
Aggiornamento: Come è discusso nei commenti qui sotto, è possibile fare qualcosa di simile a funzioni virtuali in C diritta utilizzando strutture e puntatori a funzione. Tuttavia, se sei abituato a un linguaggio come C++ che ha funzioni virtuali "vere", probabilmente troverai l'approssimazione C molto meno elegante e più difficile da usare.
in realtà, esiste una nozione di ereditarietà in C ma non rispetta il controllo ACCESS qui: http://stackoverflow.com/questions/577465/in-c-can-i-derive-a-class-from- a-struct –
@Gollum: una struttura C++ non è come C struct. – Alerty
Non è possibile farlo direttamente (manca la classe :)), ma non è un problema implementare un tale sistema utilizzando strutture e puntatori di funzione. – ManniAT
Le funzioni virtuali sono una funzione dell'orientamento agli oggetti del C++. Si riferiscono a metodi che dipendono da un'istanza di oggetto specifica piuttosto che dal tipo in cui li stai attualmente trasportando.
In altre parole: se istanziate un oggetto come Barra, quindi lo lanciate su Foo, i metodi virtuali saranno ancora quelli che erano all'istanziazione (definiti in Bar), mentre altri metodi saranno quelli di Foo.
Le funzioni virtuali vengono in genere implementate tramite vtables (che è per voi per fare più ricerche su;)).
È possibile simulare cose simili in C utilizzando le strutture come oggetti di uomo povero e salvando i puntatori di funzione in esse.
(Più correttamente, funzioni non virtuali rendono ambiguo quale classe il metodo dovrebbe essere preso da, ma in pratica ritengo C++ utilizza il tipo di corrente.)
@GCC .... Una funzione virtuale viene dichiarata nella classe Base di un oggetto e viene quindi "sovrascritta" o implementata nelle sottoclassi. Ad esempio, hai una classe Base Veicolo e crei due sottoclassi, Moto e Automobile. La classe Base dichiarerebbe una funzione virtuale di AddTires() Quindi le Sottoclassi implementerebbero questa funzione e ciascuna sottoclasse la implementerebbe in modo diverso. Una macchina ha 4 ruote, dove una moto ha 2. Non posso darti la sintassi per C o C++, però. Spero che questo aiuti
Ovviamente, la mia risposta è basata su C# e su quel modello a oggetti – MikeTWebb
perché vuoi implementare nuovamente C++? Argomenti come questo possono essere facilmente trovati nei libri e ci sono anche molti articoli online. Chiedendo questo tipo di domande, la tua reputazione sarà influenzata e le persone inizieranno a darti per scontato. Quindi fai tutto il possibile per trovare la risposta, e ancora non puoi chiedere :). –
Cosa stai cercando di ottenere? – DRL
insegnante ci ha fatto questa domanda –