1

Say I have an base struct Action:

struct Action
{
    int type;
    virtual void print() { }
}

And 2 derived structs A1, A2:

struct A1 : Action
{
    A1 : Action(0) { }
    void print() { cout << "A1"; }
}

struct A2 : Action
{
    A2 : Action(1) { }
    void print() { cout << "A2"; }
}

Then in my main function I have a stack:

stack<Action> actions;
A1 a1;
A2 a2;
actions.push(a1);
actions.push(a2);

while(!actions.empty())
{
    Action element = actions.top();
    element.print();
    actions.pop();
}

However, the print() function will always call the base class print(), instead of the derived class. How do I get it to refer to the derived class instead?

In C# I understand there is a GetType() function, but is there a similar thing in c++?

Edit: Specifically I am looking for a way to collect all objects of a similar base class into a single container, so that I can iterate through all of them, without losing information of a derived class.

Something along the lines of (in C#):

if(element.getType() == typeof(A1))
    ((A1)element).print();
else if (element.getType() == typeof(A2))
    ((A2)element).print();
John Tan
  • 1,331
  • 1
  • 19
  • 35
  • 3
    Possible duplicate of [What is object slicing?](https://stackoverflow.com/questions/274626/what-is-object-slicing) – UnholySheep Mar 02 '18 at 07:55
  • Short answer: you need to use (smart) pointers or references for polymorphism. The [`typeid` operator](http://en.cppreference.com/w/cpp/language/typeid) would be roughly the equivalent of C# `GetType()` but it won't help in this case – UnholySheep Mar 02 '18 at 07:56

1 Answers1

2

When you do actions.push(a1); and Action element = actions.top(); you are actually storing and getting copies of the actual Action that you want to store. To take advantage of virtual functions you need to access the members through pointers or references.

In your example, you would need to:

  1. Store pointers to your Actions

    stack<Action*> actions;
    A1 a1;
    A2 a2;
    actions.push(&a1);
    actions.push(&a2);
    
  2. Get those pointers and access print through them:

    while(!actions.empty())
    {
        Action* element = actions.top();
        element->print();
        actions.pop();
    }
    

    Live example.


It would be preferable to use a smart pointer like std::unique_ptr instead of a raw one but I omitted the details for the sake of simplicity.

amc176
  • 1,514
  • 8
  • 19