Create Instances of a Class During Runtime

Pages: 12
Aug 26, 2010 at 7:48am
Hi. I am new to this forum, but have been programming in c++ for a few years now. I couldn't find a thread that had this same question, and if I missed it, I'm sorry to waste your time.

Anyway, I am trying to create a basic tower defense game, but I am having some trouble figuring out how to create new instances of a class Tower during runtime. I don't want to use a predetermined array, like: Tower weak[100];, because in theory, the user could want or have more than 100 weak towers. I understand the concept of dynamic memory allocation, but from what I have read about it, it seems as though it can only be allocated once, say at the beginning of the program: int i; cin >> i; Tower weak[i];, and is, in a sense, still predetermined. I guess what I am trying to ask is, how can I dynamically create Tower weak[]; every time the user, say (for the sake of simplicity), presses a key?

I don't think it will be very helpful to solve my problem, but just in case, I am using Dev-C++ 4.9.9.2 compiler on Windows 7 platform.

Thanks in advance to any help at all.
Aug 26, 2010 at 8:04am
No, you should reread the chapter about dynamic memory allocation.
int i; cin >> i; Tower weak[i]; is not even valid C++.
Dynamic memory allocation would look like this:
Tower* weak=new Tower[i];

You can create new instances at any time during runtime using new:
1
2
Tower* newTower=new Tower();
towers.push_back(newTower);


Don't forget to delete the towers with delete (if created with new) or delete[] (if created with new[]) once they're no longer needed. A ptr_vector (such as boost's) will do that automatically for you.
Aug 26, 2010 at 8:20am
Thanks for the reply.

I guess I was just trying to paraphrase, and didn't bother to look up the right code...I won't do that again!

As for towers.push_back(newTower);, I don't know what the .push_back(newTower); part is. Is that a member I put into the class, or is it a member created with this line: Tower* newTower=new Tower(); ?

Also, yes, I would use delete, but I was just trying to make my question as clear and simple as possible, to try to avoid confusion, and also unsure if I would be using "new".

Something else I would like to ask, although I am not familiar with them, and still do not completely understand them, are vectors. Is it possible that they can be used in this case, instead of dynamic arrays?

Thanks again.
Aug 26, 2010 at 9:47am
Aug 26, 2010 at 4:45pm
Ah, thanks, I'll take a look.

I am still curious now that I've seen it, what towers.push_back(newTower); is. If it's something you can do along with dynamic memory, shouldn't it be part of the Dynamic Memory page?

Thanks.
Aug 26, 2010 at 5:12pm
Hi Flaurance,
Vector itself is a dynamic Array and .push_back is the method to enter the new element in the array.

In your case I think this would be helpful.

vector<Tower> towers;
Tower tower;
//initialize tower;
towers.push_back(tower);

Hope this is helpful.
Aug 26, 2010 at 6:35pm
Thanks for clarifying that for me, bolohardik.

If I understand your code right, you are using the information stored in "tower" to fill in a new element in the vector "towers"? So I don't really need an array of tower (Tower tower[100];). I just need one to make the base, then every time the user presses a key, use towers.push_back(tower); to add a new one to the vector?

Also, since I am using a class for the tower, and that class has many variables of different types, how can I use towers.at(4); (an access function, if I'm not mistaken), to get the access to all of the variables? Or is that something I can't do with this function? Or must I do something like this:
1
2
Tower tow_copy;
tow_copy = towers.at(4);


Thanks again.
Aug 26, 2010 at 6:59pm
Hey Flaurance,
Your first understanding is correct.vector itself is an array. You dont have to write Tower tower[100] anymore if you are using vector in this case.

For the later one, you can do something similar to the following
vector<Tower> towers;
Tower tower;
tower.member1=some_value;
tower.member2="some_value";
towers.push_back(tower);
In this way you can initialize or assign the value to the Tower class.
and then you can push it into the array(vector) of Tower.

Aug 26, 2010 at 7:12pm
A better way would be to use a vector of Tower pointers (Tower*). This would mean that only addresses are copied and thus things would be a lot faster. The most elegant way to then add a Tower pointer to your vector would be:
1
2
vector<Tower*> TowerArray;
TowerArray.push_back(new Tower()); // Call your class constructor in the most inner paranthesis 

This has two side effects, positive and negative: Positive, using Tower pointers is more light weight and is more dynamic then using Tower instances. Negative, you need to remember to delete every tower you dynamically allocate before removing it from the vector (since that would cause a memory leak).
Aug 26, 2010 at 7:20pm
Hi Kyon,
It would be helpful if you can clear the following.

vector<Tower*> TowerArray;
TowerArray.push_back(new Tower(/*Call your class constructor*/));

Do you meanIn your case, memory will be utilized only once while calling the constructor of the Tower class?
While in my case memory will be used twice, once during the call to the Tower class constructor and other while I push it into the vector?

Is my understanding correct?

Thanks.
Aug 26, 2010 at 7:52pm
vectors containing pointers (and owning the objects pointed to) violate RAII, so that is why you should use ptr_vector in this case.

Do you meanIn your case, memory will be utilized only once while calling the constructor of the Tower class?
While in my case memory will be used twice, once during the call to the Tower class constructor and other while I push it into the vector?

The point is that in your case the newly created Tower object must be copied. That either doesn't work at all (if Tower instances are non-copyable) or is slow (unless it has a simple structure).

Also, since I am using a class for the tower, and that class has many variables of different types, how can I use towers.at(4); (an access function, if I'm not mistaken), to get the access to all of the variables?


1
2
3
towers.at(4).someFunction();
//or just:
towers[4].someFunction();
Last edited on Aug 26, 2010 at 7:58pm
Aug 26, 2010 at 8:00pm
Hi Athar
I got your point about using ptr_vector and that in my case Tower object must be copied.

I have one final doubt.

(if Tower instances are non-copyable)

Do you mean Tower class has private members? or something else?

Thank you.
Aug 26, 2010 at 8:03pm
Also, since I am using a class for the tower, and that class has many variables of different types, how can I use towers.at(4); (an access function, if I'm not mistaken), to get the access to all of the variables?


As per my understanding both the ways are correct.
Aug 26, 2010 at 8:11pm
Do you mean Tower class has private members?

No, I mean that Tower might not have a public copy constructor (or should not have one (if it doesn't actually make a proper copy)).
Aug 26, 2010 at 8:27pm
Hi,

I have tried the following sample example program, I think which clearly explains what Athar wants to convey and even what I want..

#include<iostream>
#include<vector>
using namespace std;
class Item
{
public:
int a;
Item(int valA)
{
a=valA;
}
};
int main()
{
vector<Item> items;
Item item(5);
cout<<"without vector\n";
cout<<"val of a : "<<item.a<<endl;
cout<<"address of a : "<<&(item.a)<<endl;

items.push_back(item);
cout<<"with vector\n";
cout<<"val of a : "<<items[0].a<<endl;
cout<<"address of a : "<<&(items[0].a)<<endl;

vector<Item*> itemss;
Item* itemm=new Item(9);
cout<<"val of a : "<<itemm->a<<endl;
cout<<"address of a : "<<&(itemm->a)<<endl;

itemss.push_back(itemm);
cout<<"val of a : "<<itemss[0]->a<<endl;
cout<<"address of a : "<<&(itemss[0]->a)<<endl;

int a;
cin >> a;
return 0;
}


without vector
val of a : 5
address of a : 0x22ff3c
with vector
val of a : 5
address of a : 0x3e2480
val of a : 9
address of a : 0x3e24e8
val of a : 9
address of a : 0x3e24e8


Thanks Athar for your nice explanation.:)
Aug 26, 2010 at 8:32pm
This mean that using vector<Class*> is much better option than using the vector<Class>
as in the later case only memory is used once during the constructor call.
and even ptr_vector is the right way to use in this case.

Athar Pl. correct me if anything wrong or missing.

Thank you.
Aug 26, 2010 at 8:38pm
Ah. Thanks for all the help!

@Athar:

I was wondering if I could access the vectors like they were arrays...now I know that's true.

1
2
3
towers.at(4).someFunction();
//or just:
towers[4].someFunction();


This is exactly what I needed to know to access the members. Thanks!


@Kyon

I'm not completely understanding the concept of using a Tower* vector...From what I can gather, would that just point at the address of the original Tower class, or one of its implements? If that is what its doing (unless I am completely missing the point), that's not exactly what I was aiming for...


@bolohardik
(if Tower instances are non-copyable)

Do you mean Tower class has private members? or something else?


I have this same question myself. To avoid further confusion to anyone, I will gladly share what my Tower class is as of right now:

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
class Tower {
      public:
      const char * name;      //name of the tower
      char symbol;            //the tower's icon
      const char * color;     //the tower's color
      
      int x_pos;              //x position tower is placed at
      int y_pos;              //y position tower is placed at
      int range;              //region attacks can reach to
      int power;              //the attack strength
      int speed;              //how fast it attacks
      
      int price[3];           //the cost to buy it
      int upgrade[3];         //the cost to upgrade it
      int upgrade2[3];        //the cost to upgrade it
      int upgrade3[3];        //the cost to upgrade it
      int upgrade4[3];        //the cost to upgrade it
                              //(different for difficulty)
      int refund;             //money returned to remove tower
                              //(75% of tower and upgrade costs)
      int shots;              //the amount of shots taken
      int kills;              //the amount of kills acquired
      
} ;

//for simplicity:
Tower tower;


As you can see, none of my members are private, nor do I have any functions (at least, not yet...I am unsure if I will need them or not yet).

That either doesn't work at all (if Tower instances are non-copyable) or is slow (unless it has a simple structure).


If I am understanding what "non-copyable" and "simple structure" correctly, then my class should be copyable, and it seems to be 'simple structured'. Or am I missing some information about copyable and non-copyable classes?


A new question has arose. When I am using towers.push_back(tower); to add a new element of Tower, does it copy the original, unchanged class, with nothing defined? If this is true, then I suppose I would have to create a function to set the default values after it is added to the vector.

Thanks again, this is really helping!
Aug 26, 2010 at 9:15pm
Hi Flaurance,

As per my understanding, non-copyable class means the class which has private copy constructor.
This kind of classes are basically used so that there exist only one instance of the class.

In your case, there is no such requirements.


A new question has arose. When I am using towers.push_back(tower); to add a new element of Tower, does it copy the original, unchanged class, with nothing defined? If this is true, then I suppose I would have to create a function to set the default values after it is added to the vector.


we must have to set the default values or we can initialize with the parameterised constructor before doing towers.push_back(tower);

Aug 26, 2010 at 9:27pm
Okay, thanks bolohardik.

I can understand the concept of what you are saying, but I am unsure how to
initialize with the parameterised constructor


non-copyable class means the class which has private copy constructor. ... In your case, there is no such requirements.


Thanks for clarifying.
Aug 26, 2010 at 9:40pm
Hi


This kind of classes are basically used so that there exist only one instance of the class.

This was my misunderstanding.. Let me clarify that with the help of non-copyable class, we can not copy one instance to the other. But we can have more than one instances of the same class.

initialize with the parameterised constructor

That means that we need not to compulsorily set the default value.
we can have constructor like this

Class Tower
{
int a;
int b;
Tower(int x,int y)
{
a=x;
b=y;
}
};
int main()
{
Tower t(5,6);
return 0;
}

this is just an example. Not compiled one.
Pages: 12