2012-04-02 7 views
6

Sono abbastanza nuovo in C++, ma ho riscontrato un problema che non riesco a risolvere. Userò le macchine per illustrare il problema, solo per semplificare le cose. Okay, diciamo che ho una macchina di classe base e ho marchi diversi che ereditano da quella classe. In questo modo:C++ Funzione derivata dall'istanza della classe base

class Car 
{ 
    public: 
     Car(); 
}; 

class Ford: public Car 
{ 
    public: 
     Ford(); 
     void drive(); 
     void park(); 
}; 

L'idea è quella di mettere tutte queste diverse vetture insieme in un'unica un vettore di tipo Car. Mi piace così:

vector<Car*> cars; 
cars.push_back(new Ford()); 
cars.back()->drive(); //this won't work 

Come posso chiamare la funzione derivata sull'istanza della classe base? Si noti che voglio posizionarli tutti in un singolo vettore. La ragione di questo è perché voglio solo usare l'ultima istanza di classe auto derivata che è stata aggiunta (in questo caso la classe di macchina derivata è ford). Si noti inoltre che tutte le classi di auto avranno le stesse funzioni.

risposta

7

Se queste funzioni sono veramente comuni a tutte le classi derivate, allora avete un'interfaccia comune, quindi dovreste esprimerlo tramite la classe base. Per fare ciò, si dichiara queste funzioni come pura-virtual:

class Car { 
public: 
    virtual void drive() = 0; // Pure-virtual function 
}; 

class Ford : public Car { 
public: 
    virtual void drive() { std::cout << "driving Ford\n"; } 
}; 

... 

vector<Car*> cars; 
cars.push_back(new Ford()); 
cars.back()->drive(); //this will work 

[Su un lato nota, è generalmente considerato la pratica poveri di avere un vettore di puntatori prime, perché rende difficile la gestione della memoria. Dovresti considerare l'utilizzo di puntatori intelligenti.]

+0

grazie mille per la risposta ottimo e veloce, questo ha fatto il trucco. – Dan

2

Se tutti Car classi hanno le stesse funzioni poi dichiararli come puro virtual nella classe base Car:

class Car 
{ 
public: 
    Car(); 
    virtual ~Car(); 
    virtual void drive() = 0; 
    virtual void park() = 0; 
}; 

In questo modo il codice di esempio che utilizza vector a lavorare come pubblicato.

0

Può essere, se possibile, è possibile definire come classe base

class Car 
{ 
    public: 
     Car(); 
     virtual void drive(); 
}; 
0

È necessario definire l'interfaccia simile:

class Car{ 
public: 
Car(); 
virtual void moveForward(unsigned int speed) = 0; 
virtual void moveBack(unsigned int speed) = 0; 
//... 
virtual ~Car(); 
}; 

Non dimenticate di fare il distruttore virtuale. Dopodiché è sufficiente implementare questi metodi nelle classi figlie e chiamarli dopo. Anche in vettoriale è possibile utilizzare shared_ptr o semplicemente passare direttamente le istanze.

3

Hai due opzioni: o inserisci un metodo di unità virtuale() nella definizione Car o lancia i puntatori Car a puntatori Ford. Probabilmente vorrai fare il primo.

class Car 
{ 
    public: 
     Car(); 
     virtual void drive() { // default implementation} 
}; 

Ora puoi guidare() la tua auto! È inoltre possibile effettuare azionamento() una funzione virtuale pura, in questo modo:

class Car 
{ 
    public: 
     Car(); 
     virtual void drive() = 0; 
}; 

Ciò significa che non v'è alcuna implementazione predefinita per l'unità(): deve essere reimplementata in una sottoclasse.Il secondo modo ho già detto, che, ancora una volta, probabilmente non si vuole, ma dovrebbe essere incluso per completezza, è quello di gettare il puntatore:

static_cast<Ford*>(cars.back())->drive(); 

Questo funziona solo se si sa in anticipo che l'auto è una Ford , tuttavia, e non è molto utile in questo scenario. Puoi anche guardare in dynamic_cast.

+0

Sì, userò il primo metodo, ma è bello sapere che c'è un altro modo. Grazie per le informazioni! – Dan

+0

@Anthony, penso che per il secondo metodo sarebbe meglio usare un dyanamic_cast invece di un static_cast – exs

0

È necessario inserire una funzione virtuale.

Una funzione virtuale nella classe base. Nella sottoclasse è possibile implementare una funzione virtuale, per esempio è possibile specializzare il comportamento dell'unità().

È possibile trovare una faq (o tutorial) su funzioni virtuali qui:

http://www.parashift.com/c++-faq-lite/virtual-functions.html