Skip to main content
gamedev.net
🔒 Locked

Problem creating dynamic array

Started by Billy Lee Mar 9, 2003 at 10:02 AM 23 replies 600+ views
Original Post
Billy Lee
Billy Lee
I''ve been trying to create a new array of objects but I can''t get it to compile. I have defined my array called large_asteroid in global_vars.h like this: extern Asteroid *large_asteroid; // Pointer to array of (large) Asteroid objects Then in levels.cpp, I do this:
  
Asteroid *large_asteroid = NULL;

void level_1_init()
{
...
	large_asteroid = new Asteroid[2];
...
}
  
but get this compilation error: error C2512: ''Asteroid'' : no appropriate default constructor available What am I doing wrong? You don''t need a default constructor for arrays, do you?
cshireman
cshireman
Hi there. I just tried to build a small project using your code and it worked fine for me. I had to build an Asteroid class that has a default constructor in order for the ''new'' directive to work. Here is the code I used for the Asteroid class, which isn''t much, but it should get you going.

#ifndef ASTEROID_H
#define ASTEROID_H

#include <iostream.h>

class Asteroid
{
public:
Asteroid(){cout << "Building Asteroid" << endl;};
~Asteroid(){};
};

#endif

"Do or do not, there is no try." -- Yoda
Ronin Magus
Ronin Magus
Yes you need a default constructor because you aren''t sending any parameters in your new statement (which I''m not even sure you can do for arrays, because I''ve never tried!)

Anyways, slapping in an empty d.c. will probably fix your problem.
civguy
civguy
quote:
Original post by Billy Lee
What am I doing wrong? You don't need a default constructor for arrays, do you?
You do. If you want a way around it, you'll need to do it like this:

    
Asteroid** large_asteroid = new Asteroid*[2];

large_asteroid[0] = new Asteroid(23.0, 36.0);
large_asteroid[1] = new Asteroid(100.0, 35.0);

delete large_asteroid[0];
delete large_asteroid[1];
delete[] large_asteroid;

Or by using placement new on a normal array:

  
Asteroid* large_asteroid = reinterpret_cast<Asteroid*>(new char[2 * sizeof(Asteroid)]);

new (&large_asteroid[0]) Asteroid(23.0, 36.0);
new (&large_asteroid[1]) Asteroid(100.0, 35.0);

delete[] large_asteroid;
(NOT recommended, even though it's a tad faster. If you try to create a subclass of Asteroid with placement new, it'll crash)

[edited by - civguy on March 9, 2003 2:15:12 PM]
SiCrane
SiCrane
civguy, your placement new method will probably either corrupt the heap or cause an access violation (at least in release mode). In order to work properly the delete[] has to mirror the new[] used to allocate the memory. In this case the new[] was performed with a type of char, so the delete[] needs to be called on a char * pointer.

A delete[] expression performed with a class type, typically examines the memory address immediately before the passed address in order to determine the number of times it needs to call the class destructor. However, the array allocated with new [] char will have probably have different booking information in that location (typically a pointer or the number of char''s allocated). Which means the delete[] expression will then proceed to attempt to call the destructor on memory located much after the allocated memory.
civguy
civguy
Hmm. Maybe this was one of the places to use explicit destructor call then

  
Asteroid* large_asteroid = reinterpret_cast<Asteroid*>(new char[2 * sizeof(Asteroid)]);

new (&large_asteroid[0]) Asteroid(23.0, 36.0);
new (&large_asteroid[1]) Asteroid(100.0, 35.0);

large_asteroid[0].~Asteroid();
large_asteroid[1].~Asteroid();

delete[] reinterpret_cast<char*>(large_asteroid);

SiCrane
SiCrane
A better idea is just to use a std::vector.


std::vector<Asteroid> large_asteroid;
large_asteroid.push_back(Asteroid(23.0, 36.0));
large_asteroid.push_back(Asteroid(100.0, 35.0));
// destructors called when large_asteroid gets destroyed.
fizban75
fizban75
Billy Lee, you need to include the header file that defines the Asteroid class from your levels.cpp file, and also make sure the Asteroid class has a default constructor. When you create an array of two Asteroids, two actual Asteroid objects get created on the heap and they obviously need their constructors to be called in order to be created.
civguy
civguy
quote:
Original post by SiCrane
A better idea is just to use a std::vector.
But then it needs to call the copy constructor each time an element is added. </nitpick>

[edited by - civguy on March 9, 2003 3:50:11 PM]
Billy Lee
Billy Lee
Thanks for your replies, guys. I''ll try putting in a default constructor. I can now see why you need it.

In relation to this, can you create a new array which takes specific arguments to its elements. I.E. Instead of doing:

large_asteroid = new Asteroid[2];
large_asteroid[0] = Asteroid(x1,y1);
large_asteroid[1] = Asteroid(x2,y2);

can you do something like:

large_asteroid = new Asteroid {Asteroid(x1,y2), Asteroid(x2,y2)};
fizban75
fizban75
No, you can''t call constructors other than the default constructor when creating an array of class instances. You''ll have to either create an array of pointers to class instance, then loop through the pointer array and create each individual element with the parameters you want, or create each individual element and add it to an stl::vector.
Billy Lee
Billy Lee
I got it working. Now how about this one? It''s a 2-dimensional array. In global_vars.h, I''ve got this:

extern Asteroid *small_asteroid[][4];

And in levels.h:


  
Asteroid *small_asteroid[][4] = NULL;
int no_of_large_asteroids;

void level_1_init()
{
...
no_of_large_asteroids = 2;

// Create 2D array of (small) Asteroid objects

small_asteroid = new Asteroid[no_of_large_asteroids][4];
...
}


I get this error:
error C2440: ''initializing'' : cannot convert from ''const int'' to ''class Asteroid *[][4]''

in the first line of that code.
Billy Lee
Billy Lee
I''ve changed the statement in global_vars.h to:

extern Asteroid *small_asteroid; // Removed the square brackets

and the statement just above level_1_init() to:

Asteroid *small_asteroid = NULL; // Removed the square brackets

I get:

error C2440: ''='' : cannot convert from ''class Asteroid (*)[4]'' to ''class Asteroid *''

I don''t get what I''m doing wrong.
civguy
civguy
2-dimensional arrays aren''t nice in C++. And the way you''re trying to do it is very wrong.

Try this instead:

  
#include <vector>

std::vector<std::vector<Asteroid> > asteroidArray;

void level_1_init()
{
...

no_of_large_asteroids = 2;

// Create 2D array of (small) Asteroid objects


asteroidArray.clear();
asteroidArray.resize(no_of_large_asteroids, std::vector<Asteroid>(4))

...
}
Mastaba
Mastaba
Why not do something as simple as:


  
int num_asteroids;
Asteroid *pAsteroids;

void level_1_init()
{
...
num_asteroids=2;
pAsteroids=new Asteroid[num_asteroids];
pAsteroids[0].Init(23,45);
pAsteroids[1].Init(42,17);
...
}


[edited by - Mastaba on March 11, 2003 12:42:11 PM]
Mastaba
Mastaba
Actually now that I really think about it, I would probably use a double linked list for this kind of thing. That way you can easily remove a large asteroid from the list, and add small asteroids onto the list. And so on.
Billy Lee
Billy Lee
Okay, I''m using vectors now and I think I''ve got the hang of it. However, I''m getting loads and loads of errors about this line in global_vars.h:

extern std::vector > small_asteroid;

such as:

error C2146: syntax error : missing '','' before identifier ''small_asteroid''
error C2065: ''small_asteroid'' : undeclared identifier
error C2143: syntax error : missing ''>'' before '';''
warning C4091: ''extern '' : ignored on left of ''class std::vector'' when no variable is declared

It doesn''t complain about the single vector for large_asteroid though, which looks like this:

warning C4091: ''extern '' : ignored on left of ''class std::vector'' when no variable is declared

What is wrong?
Zipster
Zipster
The compiler interprets the >> as something else. Put a space between them and it won''t get confused

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.