Constucting a vector in a class - need help

If anyone has the solution for how to accomplish this, that would be awesome. What I want to do with the below code is to construct the vector containing 'Ability' objects in the class 'Card'. I have searched for the solution in the past, and have been unsuccessful, mainly because the vector contains child classes of the parent class 'Ability'. The below code is a snippet of the larger program that I am working on, and should compile:

main:
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162

#include <cstdlib>
#include <iostream>

#include <vector>
#include <string>

using namespace std;


#ifndef _abilities_h_
#define _abilities_h_

#include "abilities.h" 



class Card
{
      public:
           
           string name;
           int conv_mana_cost;
           string specific_mana;
           int power, toughness;
           string type;
           char color; //R, B, U, G, or W
           
           
           int can_block; 
           bool tapped;
           bool attacking;
           bool blocking;
           bool revealed_to_opponent;
           
           string owner; 
           
           int power_modified; 
           int toughness_modified; 
           
           int plus_1_1_counters;
           int minus_1_1_counters;
           
           int cast_preference_value;
           int cast_later_value;
           int attack_preference_value;
           int attack_later_value;
           int block_preference_value;
           int block_later_value;
           int discard_preference_value;
           int discard_later_value;
           
           int number_preference_values; 
           
           
           vector<Ability *> abilities; 
           
           
           Card( string na = "", int co = 0, string sp = "", int po = 0, int to = 0, string ty = "", char col = 'N',
                 int can_b = 1, bool tap = false, bool atta = false, bool bloc = false, bool reve = false, int powe_mod = 0, 
                 int toug_mod = 0, int plus_1_1 = 0, int minu_1_1 = 0, 
                 int cast_pref_valu = 0, int cast_late_valu = 0, int atta_pref_valu = 0, int atta_late_valu = 0, 
                 int bloc_pref_valu = 0, int bloc_late_valu = 0, int disc_pref_valu = 0, int disc_late_valu = 0,
                 int numb_pref_valu = 8 ) 
                                                                                                                          
           {
              name = na;
              conv_mana_cost = co;
              specific_mana = sp;
              power = po;
              toughness = to;
              type = ty;
              color = col;
            
            
              can_block = can_b; 
              tapped = tap;
              attacking = atta;
              blocking = bloc;
              revealed_to_opponent = reve;
               
              power_modified = powe_mod;
              toughness_modified = toug_mod; 
               
              plus_1_1_counters = plus_1_1;
              minus_1_1_counters = minu_1_1;
               
              cast_preference_value = cast_pref_valu;
              cast_later_value = cast_late_valu;
              attack_preference_value = atta_pref_valu;
              attack_later_value = atta_late_valu;
              block_preference_value = bloc_pref_valu;
              block_later_value = bloc_late_valu;
              discard_preference_value = disc_pref_valu;
              discard_later_value = disc_late_valu;
               
              number_preference_values = numb_pref_valu;                                         
              
              }

};


void fillKnownCardsVector(vector<Card *> *);

void playMatch(Card *);

void assign_values(Card *);


int main(int argc, char *argv[])
{


     vector<Card *> KnownCardsVector;

     fillKnownCardsVector( &KnownCardsVector );

     cout << KnownCardsVector[0]->abilities[0]->type;
     
     system("PAUSE");

     playMatch(KnownCardsVector[0]);



system("PAUSE");
return EXIT_SUCCESS;

}



void fillKnownCardsVector(vector<Card *> *KnownCardsVector)
{
     Card *card08 = new Card( "Mountain", 0, "None", 0, 0, "Basic Land", 'R' );

     card08->abilities.clear();
     card08->abilities.push_back(new Tap_For_R); //work?

     KnownCardsVector->push_back(card08);
}

void playMatch(Card *card01)
{
     assign_values(card01);
}

void assign_values(Card *card01)
{
     for (int l=0; l < (card01->abilities.size() + 0); l++)
          
          {
               //code taken out to simplify
          }
}





#endif //used for abilities header file 



abilities.h:

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
class Card;


class Ability
{
      public:
             int activate_preference_value;
             int activate_later_value;
             string type; 
             
             virtual int check(Card *) = 0; //for static abilities
             virtual void trigger(Card *) = 0; //for triggered abilities
             virtual void activate(Card *) = 0; //for activated abilities
             
              
               
};



class Tap_For_R : public Ability
{
      public:
             Tap_For_R() { type = "Activated", activate_preference_value = 0, activate_later_value = 0; }
             void activate(Card *self);
             void trigger(Card *self){};
             int check(Card *self){};
};        
  
  

void Tap_For_R::activate(Card *self)
{
     //code taken out to simplify
}



As you can see, in the class 'Card' I have a pretty large constructor. Up to this point, however, I have failed in my attempts to construct the abilities vector, because it contains those child classes. Any and all help is appreciated! :)
use a vector of pointers to Ability.
use a vector of pointers to Ability.


I think that I already did that, unless vector<Ability *> abilities; doesn't create a vector of pointers.

Are you saying to do: vector<Ability *> *abilities;? Does that work?
Try adding parenthesis for explicit ctor call card08->abilities.push_back(new Tap_For_R());
Try adding parenthesis for explicit ctor call card08->abilities.push_back(new Tap_For_R());


Just tried it. Didn't really do anything, the program wouldn't compile.
What are the errors?
Edit: Are you sure adding to the vector is your problem? I just ran your original code and it adds to the vector fine.
Last edited on
What are the errors?
Edit: Are you sure adding to the vector is your problem? I just ran your original code and it adds to the vector fine.


Adding to the vector is fine, right. In the larger version of the program, I have a segmentation fault later when trying to access card08->abilities.size(). I think that the segmentation fault is caused by the fact that I don't construct the vector when I create an object of type 'Card'. So, I'm trying to find out how to construct vector<Ability *> abilities; when creating an object of type 'Card'.

The larger version would be too big to post.
Last edited on
closed account (zb0S216C)
A few things:

1) The Constructor:
Use your constructor's initialisation list to initialise you data members; it's there for a reason.

2) The std::vector, abilities & Memory leaks
Don't push anything new into a std::vector - the std::vector has already reserved memory. Be sure to note that anything new'd in a std::vector will not be delete'd unless you do it. I see multiple calls to new but a severe deficiency of calls to delete.

3) Your General Parameter Types
Why are you passing everything by pointer?

Wazzak
Last edited on
The below code is a snippet of the larger program that I am working on, and should compile:
the program wouldn't compile.
I have a segmentation fault later

When you made up your mind, let me know.

cout << KnownCardsVector[0]->abilities[0]->type; Check out Demeter's Law.

1
2
3
4
#ifndef _abilities_h_
#define _abilities_h_

#include "abilities.h"  
Headers guards should go in header files. It's a lot easier.

vector<Card *> KnownCardsVector; ¿Do you plan on having polymorphism on the cards?

The larger version would be too big to post.
Then simplify it. But if you post something that does not reproduce your problem, then it's unlikely that we could help.
Your 'Card' looks like a blob, I suppose that you could transfer a big part of those members.


@Framework:
Don't push anything new into a std::vector - the std::vector has already reserved memory

¿eh? ¿where does he do a resize?
Thanks for sticking with me this far, it's been a real help. Taking your advice, I messed around with the code some more, and I've managed to recreate the bug:

main:
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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
#include <cstdlib>
#include <iostream>

#include <vector>
#include <string>

using namespace std;


#ifndef _abilities_h_
#define _abilities_h_

#include "abilities.h" 



class Card
{
      public:
           
           string name;
           int conv_mana_cost;
           string specific_mana;
           int power, toughness;
           string type;
           char color; //R, B, U, G, or W
           
           
           int can_block; 
           bool tapped;
           bool attacking;
           bool blocking;
           bool revealed_to_opponent;
           
           string owner; 
           
           int power_modified; 
           int toughness_modified; 
           
           int plus_1_1_counters;
           int minus_1_1_counters;
           
           int cast_preference_value;
           int cast_later_value;
           int attack_preference_value;
           int attack_later_value;
           int block_preference_value;
           int block_later_value;
           int discard_preference_value;
           int discard_later_value;
           
           int number_preference_values; 
           
           
           vector<Ability *> abilities; 
           
           
           Card( string na = "", int co = 0, string sp = "", int po = 0, int to = 0, string ty = "", char col = 'N',
                 int can_b = 1, bool tap = false, bool atta = false, bool bloc = false, bool reve = false, int powe_mod = 0, 
                 int toug_mod = 0, int plus_1_1 = 0, int minu_1_1 = 0, 
                 int cast_pref_valu = 0, int cast_late_valu = 0, int atta_pref_valu = 0, int atta_late_valu = 0, 
                 int bloc_pref_valu = 0, int bloc_late_valu = 0, int disc_pref_valu = 0, int disc_late_valu = 0,
                 int numb_pref_valu = 8 ) 
                                                                                                                          
           {
              name = na;
              conv_mana_cost = co;
              specific_mana = sp;
              power = po;
              toughness = to;
              type = ty;
              color = col;
            
            
              can_block = can_b; 
              tapped = tap;
              attacking = atta;
              blocking = bloc;
              revealed_to_opponent = reve;
               
              power_modified = powe_mod;
              toughness_modified = toug_mod; 
               
              plus_1_1_counters = plus_1_1;
              minus_1_1_counters = minu_1_1;
               
              cast_preference_value = cast_pref_valu;
              cast_later_value = cast_late_valu;
              attack_preference_value = atta_pref_valu;
              attack_later_value = atta_late_valu;
              block_preference_value = bloc_pref_valu;
              block_later_value = bloc_late_valu;
              discard_preference_value = disc_pref_valu;
              discard_later_value = disc_late_valu;
               
              number_preference_values = numb_pref_valu;                                         
              
              }

};

class Deck
{
      
      public:
             string name; //used to search for a specific deck
             
             vector<Card *> cardsInDeck; 
             
             Deck( string na = "", int nu = 0 )

             {
                  name = na;
             }   
};


void fillKnownCardsVector(vector<Card *> *);

void fillKnownDecksVector(vector<Deck *> *, vector<Card *> );

void playMatch(vector<Card *> );

void assign_values(Card *);


int main(int argc, char *argv[])
{


     vector<Card *> KnownCardsVector;
     
     vector<Deck *> KnownDecksVector;

     fillKnownCardsVector( &KnownCardsVector );
     
     fillKnownDecksVector(&KnownDecksVector, KnownCardsVector);

     cout << KnownCardsVector[0]->abilities[0]->type;
     
     system("PAUSE");

     playMatch(KnownDecksVector[0]->cardsInDeck);



system("PAUSE");
return EXIT_SUCCESS;

}



void fillKnownCardsVector(vector<Card *> *KnownCardsVector)
{
     Card *card08 = new Card( "Mountain", 0, "None", 0, 0, "Basic Land", 'R' );

     card08->abilities.clear();
     card08->abilities.push_back(new Tap_For_R); //work?

     KnownCardsVector->push_back(card08);
}

void fillKnownDecksVector(vector<Deck *> *KnownDecksVector, vector<Card *> KnownCardsVector) 
{
     KnownDecksVector->clear();

     Deck *deck01 = new Deck( "Mountains" ); 
          
     KnownDecksVector->push_back(deck01); //[0] in KnownDecksVector
          
     //60x Mountain
     for (int i=0; i<60; i++)
     {
               deck01->cardsInDeck.push_back(KnownCardsVector[7]); //1 Mountain 
     }    
}

void playMatch(vector<Card *> card_vector01)
{
     assign_values(card_vector01[0]);
}

void assign_values(Card *card01)
{
     
     for (int l=0; l < (card01->abilities.size() + 0); l++)
          
          {
               //loop just to illustrate the point
          }
}



#endif 


abilities.h:
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


class Card;


class Ability
{
      public:
             int activate_preference_value;
             int activate_later_value;
             string type; //activated, triggered, or static (make sure the first letter is capitalized)
             
             virtual int check(Card *) = 0; //for static abilities
             virtual void trigger(Card *) = 0; //for triggered abilities
             virtual void activate(Card *) = 0; //for activated abilities
             
              
               
};



class Tap_For_R : public Ability
{
      public:
             Tap_For_R() { type = "Activated", activate_preference_value = 0, activate_later_value = 0; }
             void activate(Card *self);
             void trigger(Card *self){};
             int check(Card *self){};
};        
  
  

void Tap_For_R::activate(Card *self)
{
     //code taken out to simplify
}

closed account (zb0S216C)
ne555 wrote:
"¿eh? ¿where does he do a resize?"

Seriously? The std::vector automatically reserves a large chuck of memory to store new objects of type T. Print the result of std::vector::capacity() (returns the size of the underlying memory).

Wazzak
@Framework:
Resize, as in modify the size
Capacity is how many objects it can hold without need to reallocate.

Now, ¿what the hell do you mean with "Don't push anything new into a std::vector..." ?


@OP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void fillKnownDecksVector(vector<Deck *> *KnownDecksVector, vector<Card *> KnownCardsVector) 
{
     KnownDecksVector->clear();

     Deck *deck01 = new Deck( "Mountains" ); 
          
     KnownDecksVector->push_back(deck01); //[0] in KnownDecksVector
          
     //60x Mountain
     for (int i=0; i<60; i++)
     {
               deck01->cardsInDeck.push_back(KnownCardsVector[7]); //1 Mountain 
     }    
}
The known cards reverse Hungarian container has just 1 element, you can't access the eight one.
Now, ¿what the hell do you mean with "Don't push anything new into a std::vector..." ?

He meant "don't use new when doing vector::push_back()"
closed account (zb0S216C)
ne555 wrote:
"Now, what the hell do you mean with "Don't push anything new into a std::vector..." ?"

Why would one prefer this:

1
2
std::vector<int *> vector_a_; 
vector_a_.push_back(new int(0));

..over this:

1
2
std::vector<int> vector_b_;
vector_b_.push_back(0);

What's the point in dynamically allocating a new int when the std::vector is more than capable of storing it in the memory it initially accumulated? Also, std::vector doesn't handle elements that were allocated with new, which of course, can leak if not properly handled.

On a side note, vector_a_ is less efficient because:

- ...with each push of vector_a_, a new block must accumulated which is a performance penalty
- ...vector_a_ could easily cause memory fragmentation with excessive calls to new
- ...objects that aren't grouped contiguously don't make effective use of the CPU cache

Wazzak
Last edited on
Because he wants to use polymorphism.
If you std::vector< Base > v; you are doing object slicing.
referring to the abilities, not the cards
Topic archived. No new replies allowed.