2010-11-17 2 views
9
class Material 
{ 
public: 
void foo() 
{ 
    cout << "Class Material"; 
} 
}; 

class Unusual_Material : public Material 
{ 
public: 
void foo() 
{ 
    cout << "Class Unusual_Material"; 
} 
}; 

int main() 
{ 
Material strange = Unusual_Material(); 
strange.foo(); //outputs "Class Material" 

return 0; 
} 

Vorrei che questo risultasse nella "Classe Unusual_Material" visualizzata alla console. C'è un modo per ottenerlo? Nel mio programma ho un materiale di classe da cui derivano altri materiali più specifici. Il metodo Material :: foo() rappresenta un metodo in Materiale che è adeguato per la maggior parte dei materiali, ma occidentalmente, un altro foo() deve essere definito per un materiale con proprietà insolite.Metodo della classe derivata dalla classe base riferimento

Tutti gli oggetti nel mio programma contengono un campo Materiale. Nel caso in cui gli venga assegnato un materiale insolito, mi piacerebbe che venisse chiamato l'insolito foo.

Probabilmente questo è piuttosto facile o impossibile, ma non riesco a capirlo in alcun modo.

Grazie

+1

Come nota, codice come 'Materiale strano = Unusual_Material();' può causare il problema affettare oggetto: http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c – birryree

risposta

19

Quello che vuoi è il polimorfismo, e per consentirle di una funzione è necessario renderlo virtual:

class Material 
{ 
public: 
    virtual void foo() // Note virtual keyword! 
    { 
     cout << "Class Material"; 
    } 
}; 

class Unusual_Material : public Material 
{ 
public: 
    void foo() // Will override foo() in the base class 
    { 
     cout << "Class Unusual_Material"; 
    } 
}; 

Inoltre, il polimorfismo funziona solo per i riferimenti e puntatori:

int main() 
{ 
    Unusual_Material unusualMaterial; 
    Material& strange = unusualMaterial; 
    strange.foo(); 
    return 0; 
} 

/* OR */ 

int main() 
{ 
    Unusual_Material unusualMaterial; 
    Material* strange = &unusualMaterial; 
    strange->foo(); 
    return 0; 
} 

Quello che hai nel tuo snippet di codice sarà slice the Unusual_Material object:

int main() 
{ 
    // Unusual_Material object will be sliced! 
    Material strange = Unusual_Material(); 
    strange.foo(); 
    return 0; 
} 
+1

Ah! grazie per averlo indicato. Immagino di aver dimenticato che il virtuale era più che la definizione di una classe astratta. Grazie per la pronta risposta! – user487100

+1

@ user487100: Va bene, finché capisci cosa è andato storto. Ti raccomando di prendere [un buon libro C++] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) però, poiché coprirà questo argomento fondamentale in molto più dettagliato –

+0

E inoltre non avevo idea di affettare. Pensavo che il programma non avrebbe avuto accesso alle parti derivate, ma immagino che, quando non si utilizza un riferimento, ciò abbia molto senso. Grazie per aver aggiunto quel pezzo alla fine per la mia edificazione. – user487100

1

Ancora migliore spiegazione sarebbe ..

class Base 
{ 
public: 
void foo()  //make virtual void foo(),have derived method invoked 
{ 
    cout << "Class Base"; 
} 
}; 
class Derived: public Base 
{ 
public: 
void foo() 
{ 
    cout << "Class Derived"; 
} 
}; 
int main() 
{ 
Base base1 = Derived(); 
Base1.foo(); //outputs "Class Base" 
      // Base object, calling base method 

Base *base2 = new Derived(); 
Base2->foo(); //outputs"Class Base",Again Base object calling base method 

// But to have base object, calling Derived method, following are the ways 
// Add virtual access modifier for base foo() method. Then do as below, to //have derived method being invoked. 
// 
// Base *base2 = new Derived(); 
// Base2->foo(); //outputs "Class Derived" . 

return 0; 
}