0

I'm fairly new to c++, and I'm trying to understand as much as possible of the language and the underlying mechanics.

I am confused about a specific case where I can't seem to access the correct member function when I have two classes (Base and Derived) even though I define them as virtual.

class Base {
  public:
  virtual void print() { std::cout << "Base" << std::endl; };
};

class Derived : public Base {
  public:
  virtual void print() { std::cout << "Derived" << std::endl; };
};

int main() {

  Base b;
  Derived d;

  b.print();
  d.print();

  Base* p1 = &b;
  Base* p2 = &d;

  p1->print();
  p2->print();

  std::vector<Base> v { b, d };

  v[0].print();
  v[1].print(); // Why doesn't this print "Derived?"

  return 0;
}

Output:

Base
Derived
Base
Derived
Base
Base <- ??

virtual seems to "work" with pointers of type Base, but not for objects in vector<Base>.

What's going on?

user3306199
  • 101
  • 7
  • 1
    You can't create vectors of baseclass objects. This is like assigning a derived object to a base object and causes "slicing" or "truncation". This is a well-known issue. – Ulrich Eckhardt Oct 27 '21 at 07:24
  • 2
    Does this answer your question? [What is object slicing?](https://stackoverflow.com/questions/274626/what-is-object-slicing) – Ulrich Eckhardt Oct 27 '21 at 07:25

1 Answers1

2

Because of object slicing. When you create your vector you copy your objects into it.

std::vector<Base> v{ b, d };

The catch is that inside the std::vector you have only objects of type Base, NOT Base and Derived. If you want polymorphic behavior with containers in C++, you usually do it with pointers, as you can't keep raw references in them.

std::vector<Base*> v{ &b, &d };
for (Base* ptr : v) {
    ptr->print();
}
Kaldrr
  • 2,780
  • 8
  • 11