Calling virtual functions through a reference to the base class

Use:

virtual void play() = 0;

Instead of:

virtual void play(){}

It prevents redundant object creation possibility.


int main ()
{ 
    instrument i,*pi;
    piano p;
    drum d; 
    pi= &i; 
    pi->play(); // - 
    pi = &p; 
    pi->play(); // pling
    pi = &d; 
    pi->play(); // dum, dum 
}

instrument &pi = i;

Here you make pi refer to the instrument object i.

pi = p;

Here you are assigning the piano object p to the object referred to by pi. The reference pi is not rebound to the piano object. It still refers to the same instrument object as before. It's just that different contents have been assigned to it using the implicitly generated default assignment operator. (In this case, the assignment has no effect, but assigning a derived type to a base type usually results in object slicing.) When you call pi.play(), the reference still refers to an instrument object and instrument::play is executed.

The point is, while you can get a pointer to point at a different object of a different type, you can't do the same with a reference. It always points at the same object. You could fix your code by using multiple references:

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

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

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