2010-06-24 15 views
18

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

+2

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 :). –

+0

Cosa stai cercando di ottenere? – DRL

+0

insegnante ci ha fatto questa domanda –

risposta

29

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.

+0

+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

+1

@ 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

+0

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

-1

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.

+1

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 –

+0

@Gollum: una struttura C++ non è come C struct. – Alerty

+2

Non è possibile farlo direttamente (manca la classe :)), ma non è un problema implementare un tale sistema utilizzando strutture e puntatori di funzione. – ManniAT

0

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.)

1

@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

+0

Ovviamente, la mia risposta è basata su C# e su quel modello a oggetti – MikeTWebb

Problemi correlati