12

This code refuses to print the appropriate messages to the console when I run it. Using pointers instead of references seems to work (-> instead of .). I am new to OOP so forgive me if you find this ridiculous.

#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
}
Venom
  • 1,107
  • 4
  • 21
  • 46
  • 13
    You cannot change a reference from the object to which it references once it bound at initialization. Right now your firing assignment operators (and triggering [object slicing](http://stackoverflow.com/questions/274626/what-is-the-slicing-problem-in-c/274634#274634) in the process). – WhozCraig Apr 21 '13 at 19:48
  • 4
    Make that an answer, will ya, sir? – jrok Apr 21 '13 at 19:51
  • A side issue, but you need to make a virtual destructor in the base class. – Peter Wood Apr 21 '13 at 20:33
  • @PeterWood: Probably a good idea. But not required as he is not calling the destructor via a base class pointer. – Martin York Apr 21 '13 at 21:46
  • possible duplicate of [Base class reference - assign other type to it](http://stackoverflow.com/questions/11065657/base-class-reference-assign-other-type-to-it) – mmmmmm Apr 23 '13 at 17:02

3 Answers3

21
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
Alan
  • 1,889
  • 2
  • 18
  • 30
Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
2
int main ()
{ 
    instrument i,*pi;
    piano p;
    drum d; 
    pi= &i; 
    pi->play(); // - 
    pi = &p; 
    pi->play(); // pling
    pi = &d; 
    pi->play(); // dum, dum 
}
Kevin
  • 16,549
  • 8
  • 60
  • 74
Hawk amore
  • 21
  • 1
  • 5
    Welcome to StackOverflow! Please add an explanation to supplement your code in your post. – Kevin Nov 09 '19 at 16:54
1

Use:

virtual void play() = 0;

Instead of:

virtual void play(){}

It prevents redundant object creation possibility.

Abhishek Oza
  • 3,340
  • 1
  • 27
  • 35