1

I looked around, and most questions deal with why you would use virtual, what polymorphism is and so on. I am having a problem in my program and I want to know WHY the child function is not being called and how to actually CALL the child function in this situation.

I can emulate my problem:

#include <string>
#include <iostream>
#include <vector>

class BaseA {
  public:
  BaseA(const std::string &n)
    : name(n)
  {
  }

  virtual void print() const
  {
    std::string str("");
    str += name;
    std::cout << str << std::endl;
  }

  protected:
  std::string name;
};

class BaseB : public BaseA {
  public:
  BaseB(const std::string &n, const std::string &v)
    : BaseA(n), value(v)
  {
  }

  void print() const
  {
    std::string str("");
    str += name;
    str += ' ';
    str += value;
    std::cout << str << std::endl;
  }

  private:
  std::string value;
};

int main() {
  std::vector<BaseA> vec;
  vec.push_back(BaseA("cat"));
  vec.push_back(BaseB("cat", "kitten"));

  for(BaseA &obj : vec)
    obj.print();

  return 0;
}


Why is the output: cat cat?

How do I change the output to "cat cat kitten " using BaseB::print()?

Benjamin
  • 1,832
  • 1
  • 17
  • 27
  • This is mostly very true @remyabel. I'd like to point out in my defense, if you don't know the term is coined as SLICING, it's rather difficult to discover the correct question without showing it visually. – Benjamin Nov 18 '14 at 18:29
  • @Ben It's an automatic comment when you close vote. There's no offense intended. –  Nov 18 '14 at 18:30
  • @remyabel None taken. Onwards. – Benjamin Nov 18 '14 at 18:33

1 Answers1

4

As pointed out by rightføld, you are victim of the slicing problem. However, since your question is tagged C++11, you can take advantage of std::unique_ptr.

std::vector<std::unique_ptr<BaseA>> vec;
vec.push_back(std::make_unique<BaseA>("cat"));
vec.push_back(std::make_unique<BaseB>("cat", "kitten"));

for(std::unique_ptr<BaseA>& obj : vec)
    obj->print();

Unfortunately std::make_unique was not added until C++14, you may choose to use emplace_back instead.

std::vector<std::unique_ptr<BaseA>> vec;
vec.emplace_back(new BaseA("cat"));
vec.emplace_back(new BaseB("cat", "kitten"));

for(std::unique_ptr<BaseA>& obj : vec)
    obj->print();
  • This answer is extremely helpful and solves my problem elegantly. Thank you @remyabel. – Benjamin Nov 18 '14 at 18:41
  • When does the actual Slice happen? Could you point that out in your answer possibly? Is it the moment I push the Object onto the vector? – Benjamin Nov 18 '14 at 18:41
  • 1
    @Ben [Learning C++: polymorphism and slicing](https://stackoverflow.com/questions/4403726/learning-c-polymorphism-and-slicing) may be illuminating (admittedly, it does a better job of explaining than the proposed duplicate.) –  Nov 18 '14 at 18:46
  • Thanks again @remyabel. It does explain it much better I agree. One really must remember how diverse C++ is and how close its syntax brings you to the machine. – Benjamin Nov 18 '14 at 18:56
  • 1
    Note: the emplace version as specified can leak memory if emplace_back causes the vector to grow and there isn't enough memory. – Nevin Nov 18 '14 at 20:58
  • If anyone plans on placing the objects in other vectors like I am, use std::shared_ptr instead of std::unique_ptr. – Benjamin Nov 19 '14 at 01:41