Call derived class method from base class reference

user487100 picture user487100 · Nov 17, 2010 · Viewed 16.7k times · Source
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;
}

I would like for this to result in the "Class Unusual_Material" being displayed to the console. Is there a way I can achieve this? In my program I have a class Material from which other more specific materials are derived. The method Material::foo() represents a method in Material that is adequate for most materials, but occationally, another foo() needs to be defined for a material with unusual properties.

All objects in my program contain a Material field. In the event that they are assigned an unusual material, I would like the derived, unusual foo to be called.

This is probably either pretty easy, or impossible, but I can't figure it out either way.

Thanks

Answer

In silico picture In silico · Nov 17, 2010

What you want is polymorphism, and to enable it for a function you need to make it 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"; 
    } 
}; 

Also, polymorphism only works for references and pointers:

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

What you have in your code snippet will slice the Unusual_Material object:

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