polymorphism code not doing what I want

Feb 27, 2017 at 3:41pm
Hi guys I want to create an array of monster objects and have each individual monster attack for example a ghost object should use it's attack,I set a virtual function but everytime I run this code instead of the ghost or ninjas attack function getting called the monster attack function gets called,does anybody know why this is happening? and how I can fix this?

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
67
68
69
70
71
72
73
74
75
  #include <iostream>

using namespace std;


class monster{

  protected:

      int attack;

 public:

    virtual void Attack(){

       cout << "monster attack" << endl;

    }

    void setAttackPower(int n){

         attack = n;
    }

};

class ninja: public monster{


 public:

       void Attack(){


            cout << "ninja attack" << attack << endl;

       }

};

class ghost: public monster{

  public:


      void Attack(){


          cout << "ghost attack" << attack << endl;

      }
};


int main()
{

    ninja nin;
    monster *one = &nin;

    ghost go;
    monster *two = &go;

    monster monList[2];
    monList[0] = nin;
    monList[1] = go;

    for(int i = 0; i < 2; i++){

        monList[i].Attack();

    }

}



I also tried doing this but got a compiler error and not sure why

1
2
3
4
5
6
7
8
9
10
11
12

ninja nin;
    monster *one = &nin;

    ghost go;
    monster *two = &go;

    monster *m = new monster[2];

    m[0] = &nin;

Last edited on Feb 27, 2017 at 3:53pm
Feb 27, 2017 at 4:01pm
closed account (48T7M4Gy)
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
#include <iostream>

using namespace std;

class monster{
    
protected:
    
    int attack;
    
public:
    
    virtual void Attack(){
        
        cout << "monster attack" << endl;
        
    }
    
    void setAttackPower(int n){
        
        attack = n;
    }
    
};

class ninja: public monster{
    
    
public:
    
    void Attack(){
        
        
        cout << "ninja attack" << attack << endl;
        
    }
    
};

class ghost: public monster{
    
public:
    void Attack(){
        cout << "ghost attack" << attack << endl;
    }
};


int main()
{
    
    ninja nin;
    ghost go;
    
    monster* monList[2];
    monList[0] = &nin;
    monList[1] = &go;
    
    for(int i = 0; i < 2; i++){
        
        monList[i] -> Attack();
        
    }
    
}

ninja attack0
ghost attack58560
Program ended with exit code: 0
Last edited on Feb 27, 2017 at 4:02pm
Feb 27, 2017 at 4:06pm
closed account (48T7M4Gy)
BTW n should be initialised (defaulted) to get rid of those junk values being displayed.
Feb 27, 2017 at 4:16pm
does anybody know why this is happening?


http://stackoverflow.com/questions/15188894/why-doesnt-polymorphism-work-without-pointers-references - particularly the second para of the accepted answer
Feb 27, 2017 at 8:40pm
thanks guys

just wondering how come the code which you posted works(displays each class's own attack function)

1
2
3
4
5
6
7
8
9
10
11
12
13

ninja nin;
    ghost go;
    
    monster* monList[2];
    monList[0] = &nin;
    monList[1] = &go;
    
    for(int i = 0; i < 2; i++){
        
        monList[i] -> Attack();
        




and this doesn't(just displays the default monster's attack function)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19


ninja nin;
    monster *one = &nin;

    ghost go;
    monster *two = &go;

    monster monList[2];
    monList[0] = nin;
    monList[1] = go;

    for(int i = 0; i < 2; i++){

        monList[i].Attack();

    }

Last edited on Feb 27, 2017 at 8:47pm
Feb 27, 2017 at 10:29pm
closed account (48T7M4Gy)
just wondering how come the code which you posted works(displays each class's own attack function)


The reason is as the article from gunnerfunner explains. The overall problem is called 'slicing' where saving the various inherited objects as objects slices the information so that they 'become' base class objects on retrieval. To overcome this the objects must be saved as pointers. In this case they are saved as an array of pointers to monsters, not an array of monsters.

So when they are recalled from the array the elements are pointers so '->' instead of '.' applies.

Your main() should be:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main()
{
    
    ninja nin;
    monster *one = &nin;
    
    ghost go;
    monster *two = &go;
    
    monster *monList[2];
    monList[0] = one;
    monList[1] = two;
    
    for(int i = 0; i < 2; i++){
        
        monList[i]->Attack();
        
    }
    
}
Last edited on Feb 27, 2017 at 11:15pm
Feb 28, 2017 at 3:39am
closed account (48T7M4Gy)
Or more to the point:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int main()
{
    
    ninja nin;
    ninja *one = &nin;
    
    ghost go;
    ghost *two = &go;
    
    monster* monList[2];
    monList[0] = one;
    monList[1] = two;
    
    for(int i = 0; i < 2; i++){
        
        monList[i] -> Attack();
        
    }
    
    return 0;
    
}
ninja attack0
ghost attack58656
Program ended with exit code: 0
Last edited on Feb 28, 2017 at 3:40am
Feb 28, 2017 at 1:42pm
thanks Kemort,that's the first time I've heard of slicing something new to learn :)
Topic archived. No new replies allowed.