2010-11-17 33 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; 
} 

Je souhaite que cela entraîne l'affichage de la "Class Unusual_Material" sur la console. Est-ce que je peux y arriver? Dans mon programme, j'ai un matériau de classe à partir duquel d'autres matériaux plus spécifiques sont dérivés. La méthode Material :: foo() représente une méthode dans Material qui est adéquate pour la plupart des matériaux, mais à l'occasion, un autre foo() doit être défini pour un matériau avec des propriétés inhabituelles.Méthode de classe dérivée d'appel à partir de la référence de classe de base

Tous les objets de mon programme contiennent un champ Matériau. Dans le cas où ils sont affectés d'un matériel inhabituel, je voudrais que le foo dérivé, inhabituel soit appelé.

C'est probablement soit facile, soit impossible, mais je ne peux pas le comprendre de toute façon.

Merci

+1

Comme une note, le code comme 'étrange = Unusual_Material() Matériel,' peut entraîner le problème de découpage en tranches d'objet: http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c – birryree

Répondre

19

Ce que vous voulez est le polymorphisme, et pour lui permettre d'une fonction que vous devez faire 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"; 
    } 
}; 

En outre, le polymorphisme ne fonctionne que pour les références et pointeurs:

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; 
} 

Ce que vous avez dans votre extrait de code sera slice the Unusual_Material object:

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

Ah! Merci d'avoir fait remarquer cela. Je suppose que j'ai oublié que le virtuel était plus que de définir une classe abstraite. Merci pour votre réponse rapide! – user487100

+1

@ user487100: C'est bon, tant que vous vous rendez compte de ce qui n'a pas fonctionné. Je vous recommande de choisir [un bon livre en C++] (http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list), car il couvrira ce sujet fondamental dans beaucoup plus de détails. –

+0

Et je n'avais aucune idée de trancher. Je pensais que le programme n'aurait tout simplement pas accès aux parties dérivées, mais j'imagine que, lorsque vous n'utilisez pas de référence, cela a beaucoup de sens. Merci d'avoir ajouté ce petit bout à la fin pour mon édification. – user487100

1

encore meilleure explication serait ..

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; 
}