2013-04-21 26 views
6

Questo codice si rifiuta di stampare i messaggi appropriati sulla console quando viene eseguito. Usare i puntatori invece dei riferimenti sembra funzionare (-> invece di.). Sono nuovo di OOP quindi perdonami se trovi questo ridicolo.Chiamare funzioni virtuali tramite un riferimento alla classe base

#include <iostream> 

using namespace std; 

class instrument { 
public: 
    virtual void play(){} 
}; 

class drum : public instrument { 
public: 
    void play(){ 
     cout << "dum, dum" << endl; 
    } 
}; 

class piano : public instrument { 
public: 
    void play(){ 
     cout << "pling" << endl; 
    } 
}; 

int main(){ 
    instrument i; 
    piano p; 
    drum d; 

    instrument &pi = i; 
    pi.play(); // - 

    pi = p; 
    pi.play(); // pling 

    pi = d; 
    pi.play(); // dum, dum 
} 
+9

Non è possibile modificare un riferimento dall'oggetto a cui fa riferimento una volta associato all'inizializzazione. In questo momento i tuoi operatori di assegnazione di attivazione (e attivazione di [object slicing] (http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c/274634#274634) nel processo). – WhozCraig

+4

Fai una risposta, vero signore? – jrok

+0

Un problema secondario, ma è necessario creare un distruttore virtuale nella classe base. –

risposta

15
instrument &pi = i; 

Qui si fanno pi riferiscono alla instrument oggetto i.

pi = p; 

Qui si sta assegnando l'oggetto pianop all'oggetto a cui si riferisce pi. Il riferimento pi non è un ritorno all'oggetto piano. Si riferisce ancora allo stesso oggetto instrument come prima. È solo che diversi contenuti sono stati assegnati ad esso utilizzando l'operatore di assegnazione di default generato in modo implicito. (In questo caso, l'assegnazione non ha alcun effetto, ma l'assegnazione di un tipo derivato a un tipo base di solito si traduce in segmentazione degli oggetti.) Quando si chiama pi.play(), il riferimento fa ancora riferimento a un oggetto instrument e viene eseguito instrument::play.

Il punto è, mentre è possibile ottenere un puntatore per puntare a un oggetto diverso di un tipo diverso, non è possibile fare lo stesso con un riferimento. Punta sempre sullo stesso oggetto. È possibile correggere il codice utilizzando più riferimenti:

instrument &pi = i; 
pi.play(); // - 

instrument &pp = p; 
pp.play(); // pling 

instrument &pd = d; 
pd.play(); // dum, dum 
+1

I puntatori sono un po 'di più versatile e flessibile rispetto ai riferimenti, no? – Venom

+0

@ n. entrambi hanno i loro usi –

+1

@Venom Potrebbero essere più flessibili se si considera solo la loro funzionalità non elaborata. Tuttavia, non sempre si vuole quella flessibilità. In realtà, potrebbe anche portare a problemi. Scegli il tipo appropriato per il lavoro. –

Problemi correlati