Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ cast to base class [duplicate]

I have a base class A and a derived class B.

class A {
public:
    int x;
    virtual int getX() {
        return x;
    }
};

class B : public A {
public:
    int y;
};

The virtual function is there just to make it polymorphic. Next i declare a list of A's but put B's inside:

vector<A> list;
B b1,b2;
b1.y = 2;
b2.x = 10;

list.push_back(b1);
list.push_back(b2);

Now i want to go over all elements on the vector and access the y member (which only B's have):

for (auto it = list.begin(); it != list.end(); ++it) {
    B &cast = dynamic_cast<B&>(*it);
    int value = cast.y;
    std::cout << value << std::endl;
}

This code gives a runtime error. Any idea how can i do the cast and access y?

like image 798
André Santos Avatar asked Mar 20 '17 19:03

André Santos


1 Answers

Whats is happening is an object slice.

One way to achieve what you are looking for is:

#include <vector>
#include <iostream>

using namespace std;

class A {
  public:
    int x;
    virtual int getX() {
      return x;
    }

    virtual ~A() = default;
};

class B : public A {
  public:
    int y;
};

int main() {
  vector<A*> list;
  B b1,b2;
  b1.y = 2;
  b2.x = 10;

  list.push_back(&b1);
  list.push_back(&b2);

  for (auto it = list.begin(); it != list.end(); ++it) {
    B* cast = dynamic_cast<B*>(*it);
    int value = cast->y;
    std::cout << value << std::endl;
  }

  return 0;
}

In this sample code, we are using pointers to avoid the object slice.
As stated by cdhowie : runtime polymorphism requires the use of pointers or references

Another important thing: when creating class hierarchies, always make your base class destructor virtual or you will have memory problems

like image 152
rcmgleite Avatar answered Oct 07 '22 01:10

rcmgleite