0

I am trying to do something that I feel should be more straightforward or maybe my Java knowledge is interfering, but I can't figure it out.

All I want to do is make a vector<A> as {aa, bb, cc} where bb and cc are child instances of the base class, A. Each Child class uses the same function name but has a different implementation. So what I want to do is call that implementation during the iteration.

Here's my attempt.

#include <iostream>
#include <vector>

class A {
  public: 
    virtual ~A() = default;
};

class B: public A {
  public:
    int h() {
      return 2;
    }
};

class C: public A {
  public:
    int h() {
      return 3;
    }
};

int main() {
  std::cout << "hello world" << std::endl;
  
  // Inheritance
  A aa;
  B bb;
  C cc;

  std::vector<A> as {aa, bb, cc};

  for (A child: as) {
    if (typeid(B) == typeid(child)) {
      std::cout << "child is a B" << std::endl;
      B* child_b_p= static_cast<B*>(&child);
      std::cout << child_b_p -> h() << std::endl;
    }
    
    if (typeid(C) == typeid(child)) {
      std::cout << "child is a C" << std::endl;
      C* child_c_p= static_cast<C*>(&child);
      std::cout << child_c_p -> h() << std::endl;
    }
  }

  return 0;
}

I expect

child is a B
2
child is a C
3

I only see hello world. What is a possible workaround for object slicing in this case?

under_the_sea_salad
  • 1,754
  • 3
  • 22
  • 42

1 Answers1

1

You are suffering from object slicing. Polymorphism only works when using pointers/references to objects, which you are not.

Also, this code:

if (typeid(B) == typeid(child)) {
    ...
    B* child_b_p = static_cast<B*>(&child);
    ...
}

Should be written to use dynamic_cast instead of typeid().

Try this instead:

#include <iostream>
#include <vector>

class A {
  public: 
    virtual ~A() = default;
};

class B: public A {
  public:
    int h() {
      return 2;
    }
};

class C: public A {
  public:
    int h() {
      return 3;
    }
};

int main() {
  std::cout << "hello world" << std::endl;
  
  // Inheritance
  A aa;
  B bb;
  C cc;

  std::vector<A*> as {&aa, &bb, &cc};

  for (A* child : as) {
    if (B* child_b_p = dynamic_cast<B*>(child)) {
      std::cout << "child is a B" << std::endl;
      std::cout << child_b_p->h() << std::endl;
    }
    
    if (C* child_c_p = dynamic_cast<C*>(child)) {
      std::cout << "child is a C" << std::endl;
      std::cout << child_c_p->h() << std::endl;
    }
  }

  return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770