2

I'm wondering how polymorphism in C++ works when an object you're acting on is stored inside a class (not as a pointer or reference type).

I've read that polymorphism will only work on pointers and references, however I've overloaded the << operator, which will take in a reference to A.

In testing this example in my implementation, I find it doesn't work as expected and will return the base class string ("A") instead of "B".

Is this because the object is stored inside the class itself? and the << operator taking in a reference has nothing to do with the workings of polymorphism? (ie. because the object at it's core is stored in the class, it won't work unless I store it as a pointer/reference in the class) Thanks

class Test {

    public:
       void Run() {
           object_ = B();
           std::cout << object_ << std::endl;
       }


    private:
       A object_;
};

Class A {
    // Assume this is already implemented. All it does it add obj.getType()
    // to stream
    friend ostream& operator<<(ostream& stream, A obj);

    public:
      virtual std::string getType() {
             return std::string("A");
      }
};

Class B : public A {
    public:
      std::string getType() {
            return std::string("B");
      }
};

int main(int argc, char* argv[]) {
    Test test = Test();
    test.Run();
}
Antix
  • 369
  • 3
  • 19
  • duplicate: http://stackoverflow.com/questions/4403726/learning-c-polymorphism-and-slicing - this is called "slicing", nothing to do with `object_` being a class member. – Mat Sep 02 '12 at 15:21
  • That's the term I was looking for, cheers – Antix Sep 02 '12 at 15:30

1 Answers1

2

You have an A object in your class, so when you do this:

object_ = B();

the B object on the RHS is sliced. See object slicing. This is independent of the objects being members of a class, and can be illustrated with a simpler example:

int main()
{
  B b;
  A a;
  a = b;
  std::cout << a << "\n";
}
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • So if I were to change the A object type to an A* inside Test, it would work without slicing? – Antix Sep 02 '12 at 15:29
  • 1
    @Antix make sure to delete any newed pointers, or use a smart pointer instead of a raw one. – juanchopanza Sep 02 '12 at 15:35
  • If I'm on the right track, that would be to avoid memory leaks? – Antix Sep 02 '12 at 15:36
  • @Antix yes. Well, strictly, so that the necessary destructors get called. These could do more than release resources, they could close file handles, sockets, reduce reference counts... – juanchopanza Sep 02 '12 at 15:38
  • I would add that the slicing is done because if an object B inheriting from A has a bigger size than object A, there is no space for the extra data in the "Test" class. That's why you can't directly polymorph a member object. – Offirmo Sep 02 '12 at 15:41