Dynamic allocated array of objects

Sep 9, 2019 at 1:16am
I am trying to write a simpler version of a zoo tycoon game that allows the user to buy animals. I have a class, Zoo that has it's own class, lion. Each time a lion is bought I want to create a lion object that is stored in an array on the heap, so it needs to use 'new'. My problem is, after instantiating the first lion, all subsequent lion's address' in their constructor is different than the address where I give them a random age!

Zoo.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
40
41
42
43
44
45
46
47
48
 #ifndef ZOO_H
#define ZOO_H
#include "Lion.h"

class Zoo
{
private:
	Lion *lion;
	int turn;
	int index;
public:
	Zoo():lion(new Lion[1] ), turn(0),index(0)
	{
		//cout<<"Zoo constructor at " << this << endl;
		cout << endl;
	}

	void gameLoop()
	{
		int x = 0;
		while (turn < 2)
		{
			if (turn == 0)
			{
				lion[index].data(lion);
				turn++;
			}
			else
			{
				index++;
				lion[index].data(new Lion[1]);
				turn++;
				
			}

		}
		
	}

	~Zoo()
	{
		cout << "Zoo destruct" << " at " << this << endl;
		delete[] lion;
	}
	
};

#endif 

Lion.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
#ifndef LION_H
#define LION_H
#include<iostream>

using namespace std;
class Lion
{
private:
	int age;
public:
	Lion():age(0)
	{
		cout << "Lion construct at address "<<this << endl;
	}

	void data(Lion* L)
	{
		age = rand() % 500 + 1;
		cout << "age: " << age << " address " << this << endl;
	}
	
	
	~Lion()
	{
		cout << "Lion destruct" << endl;
	}
};

#endif 

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

#include"Zoo.h"

int main()
{
	Zoo zoo;
	zoo.gameLoop();

	system("Pause");
	return 0;
}


My problem seems to arise from this section

else
{
index++;
lion[index].data(new Lion[1]);
turn++;

}

The new constructor that
lion[index].data(new Lion[1]);
creates always has a different address than what is shown in display for every increment of turn after 0.

Not sure how I make the addresses the same!

My output is

Lion construct at address 012F21A4

age: 42 address 012F21A4
Lion construct at address 012F239C
age: 468 address 012F21A8
Press any key to continue . . .








Last edited on Sep 9, 2019 at 1:36am
Sep 9, 2019 at 2:20am
You're missing something about what new does.

Line 11 of zoo.h creates ONE lion object and assigns the lion member to point to it.

At line 30 you increment index and then access lion[index]. But since lion points to an array of size 1, any index other than zero is invalid.

Also, why does the data() member take a Lion object as a parameter? You don't use the parameter so there's no reason to pass is.

If the zoo can have multiple lions then I suggest a vector<Lion>. Let vector<> handle the memory management for you. That's what it's there for.
Sep 9, 2019 at 2:40am
"Also, why does the data() member take a Lion object as a parameter? You don't use the parameter so there's no reason to pass is." Originally I called data like lion[index].data(); but I would only have one Lion on constructor. So lion.data(Lion&) really doesn't do anything :/ I haven't worked with vectors much before, I'll give it a try. Does vector assign data to the heap or stack? Basically I am wondering if I should use "new" with my program.
I'll try this
https://www.youtube.com/watch?v=iPlW5tSUOUM
Last edited on Sep 9, 2019 at 2:46am
Sep 9, 2019 at 3:57am
So I have the following now
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private:
	//std::vector<datatype> array_name;
	//Lion lion; //*lion points to an array of lion objects?
	vector<Lion> lion;
	int turn;
	int index;
public:
	   //construct a lion and assign it's address?
	Zoo():lion(), turn(0),index(0)																//B():a(new A){}
	{
		cout<<"Zoo constructor at " << this << endl;
		cout << endl;
	}


but now I can't call the constructor for lion. Then I was thinking, well what if I have a pointer to lion and send the address in. So I declared the lion object in zoo

vector<Lion> *lion;

and then did a constructor initializer list like:

Zoo():lion(new vector<Lion>), turn(0),index(0)

how do I call the lion constructor from zoo with a vector object?
Sep 9, 2019 at 4:23am
You don't need to explicitly call the constructor for lion if it's an std::vector (as opposed to a pointer to one). Really. I swear. The default constructor will get called.

-Albatross
Sep 9, 2019 at 4:44am
Oh no, I believe you. I know I am doing something wrong. Here is my simple program...

Zoo.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef ZOO_H
#define ZOO_H
#include<iostream>
#include"Giraffe.h"
#include<vector>
using namespace std;
class Zoo
{
private:
	vector<Giraffe> giraffe;
public:
	Zoo():giraffe()
	{
		cout << "Zoo constructor" << endl;
	}

	void loop()
	{
		giraffe[0].print();
	}
	~Zoo(){}
};
#endif  

Giraffe.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef GIRAFFE_H
#define GIRAFFE_H
#include<iostream>

using namespace std;
class Giraffe
{
public:
	Giraffe()
	{
		cout << "Giraffe constructor" << endl;
	}

	void print()
	{
		cout << "Hello world" << endl;
	}
	~Giraffe(){}
};
#endif

 

main.cpp
1
2
3
4
5
6
7
8
#include "Zoo.h"

int main()
{
	Zoo zoo;
	
	return 0;
} 


and my output is

Zoo constructor
Press any key to continue . . .

Lol, what am I doing wrong?
Sep 9, 2019 at 4:59am
Well, the constructor for your Zoo runs, but an std::vector starts out empty, without any objects in it. Thus, your Giraffe constructor never gets called. You can add or remove objects to it (the vector) as needed, and there is a constructor that you can call to construct it with a specific number of objects already in it.

For more info, here's a thing I wrote on them years ago that'll hopefully be helpful: http://www.cplusplus.com/articles/37Mf92yv/

-Albatross
Sep 9, 2019 at 3:07pm
I suspect that others here will disagree, but for now, I'd just make the lion vector public. You're going to want to access those lions after all.

1
2
3
4
5
6
class Zoo {
public:
    vector<Lion> lions;
    ...
};
Zoo myZoo;


To add a lion:
1
2
lion tmp;
myZoo.lions.push_back(tmp);


Get rid of Lion::data(). That logic belongs in the constructor. In other words, a new lion always gets a random age, right?
Topic archived. No new replies allowed.