0

0I'm quite rusty at C++. I've tried various searches but can't come up with an answer. I have the following code:

class Base
{
  public:
    Base() {};
    virtual void hello() { std::cout << "I'm the base class" << std::endl; }
};

class Alice : public Base
{
  public:
    Alice() {};
    virtual void hello() { std::cout << "I'm Alice" << std::endl; }
};


class Bob : public Base
{
  public:
    Bob() {};
    virtual void hello() { std::cout << "I'm Bob" << std::endl; }
};


Base test(int alice)
{
  if(alice)
    return Alice();
  else
    return Bob();
}


int main()
{
  Base a = test(0);
  Base b = test(1);

  a.hello();
  b.hello();
}

I would expect the output to be

I'm Alice
I'm Bob

but instead it is

I'm the base class
I'm the base class

What (aside from Python-on-the-brain) is going on here?

Dan
  • 2,766
  • 3
  • 27
  • 28

1 Answers1

3

The return type of test is Base. That means it returns Bases and Bases only. No Alices or Bobs will be returned from that function. When you do return Alice(); or return Bob(); the Base parts of those objects get sliced out and returned.

Likewise, the objects a and b in main are of type Base and that's all they'll ever be. That's why, when you call hello on them, you are invoking the Base implementation.

In C++, you can take advantage of polymorphism by using pointers or references. That is, a Base* or a Base& can point at or refer to an Alice or a Bob object. Then, when you attempt to call a virtual member function through that pointer or reference, the appropriate implementation of the function will be determined by looking at the run-time type of the object.

As a simple test, you could dynamically allocate your Alice and Bob objects and return a pointer to them:

Base* test(int alice)
{
  if(alice)
    return new Alice();
  else
    return new Bob();
}

You'll need to make a and b have type Base* and then call hello with, for example, a->hello(). However, if you dynamically allocate objects like this, you have to remember to delete them. Better, use a smart pointer like std::unique_ptr, for which polymorphism will still work.

Also note that if you want to use these types polymorphically, you should implement a virtual destructor.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324