Polymorphism

hi guys so this is a pretty basic question which I probably should know by now but I'm going to bite the bullet and ask it anyway

So the question is how come living.hello() gets printed out in my pointers example in the for loop,instead of Monster hello or cat hello?

I used the virtual keyword to say that I want to use polymorphism anyway why is this happening is slicing occuring?

and how would I make this work the way I want it to,and also why?

thanks


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

#include <iostream>
#include <vector>

using namespace std;

class living{

public:

     living(){};

virtual void hello(){
   cout << "living hello" << endl;
}

};

class Monster : public living{

public:
     Monster(){}
     virtual void hello(){

        cout << "Monster hello" << endl;
     }
};

class Cat : public living{

 public:

   Cat(){}
    virtual void hello(){

   cout << "cat hello" << endl;
   }
};

int main()
{
    living one;
    one.hello();
    Monster mon;
    mon.hello();
    Cat cat;
    cat.hello();

    // pointers

    living *a = new living();
    living *b = new Monster();
    living *c = new Cat();

    vector<living> things;
    things.push_back(*a);
    things.push_back(*b);
    things.push_back(*c);

    for(int i = 0; i < things.size(); i++){

        things.at(i).hello();
    }
}




** EDIT also how come when I use the pointers in this way as shown in the code below it works fine and prints monster and cat hello

1
2
3
4
5
6
7
8
9
10
 // pointers again but differently

    Monster x;
    Cat y;
    living* p_x = &x;
    living* p_y = &y;

    p_x->hello();
    p_y->hello();
Last edited on
Your vector is a vector of living. Not a vector of pointers.

So when each object is copied into the vector, they are "sliced". In effect, they are cut down to just being objects of type living. Looks up "object slicing" for the full details.

If you made it a vector of pointers, it would work as you expect.
I remember this being a bit confusing back when I was first introduced to it. What's happening in your first example is something called object slicing. You can search the term if you'd like.

Polymorphism only works on pointers and references. When you declare an std::vector<living> and push_back an element, that element is being copied into a value, not a reference.

When a subclass gets assigned or copied to a base class, there is no place for the base class to hold the subclass's information. It is simply not copied, or you can think of it as being stripped out.

You either have to make a vector of pointers, or you can use an std::reference_wrapper.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

#include <iostream>
#include <vector>
#include <functional>

using namespace std;

class living{
public:
virtual void hello(){
   cout << "living hello" << endl;
}
};

class Monster : public living{
public:
     virtual void hello(){
        cout << "Monster hello" << endl;
     }
};

class Cat : public living{
 public:
    virtual void hello(){
   cout << "cat hello" << endl;
   }
};

int main()
{
    // pointers

    living *a = new living();
    living *b = new Monster();
    living *c = new Cat();

    std::vector<std::reference_wrapper<living>> things;
    
    things.push_back(*a);
    things.push_back(*b);
    things.push_back(*c);

    for (size_t i = 0; i < things.size(); i++){

        things.at(i).get().hello();
    }
}


** EDIT also how come when I use the pointers in this way as shown in the code below it works fine and prints monster and cat hello

Because that's how polymorphism works normally -- through a pointer (p_x) or a reference.
Last edited on
thanks guys that makes a lot of sense now :)
Registered users can post here. Sign in or register to post.