tags:

views:

141

answers:

6

Hi,

I'm using C++ to create a tile map for a game. My problem is, I want to populate a multidimensional array of ints in the Map constructor, but it's not working properly. Here's my code in "Map.h" (irrelevant code has been removed).

class Map {

private:    
int mapArray[15][20];

};

And my code from Map.cpp

Map::Map()
{

    mapArray = {
     { 0,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,197,198,199 },
     { 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219 },
     { 220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 },
     { 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259 },
     { 260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279 },
     { 280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299 }
    };


}

PS. creating the mapArray locally, within a member function using int mapArray[15][20] and populating it then is working fine, I just can't seem to get it to populate in the constructor, with a member variable.

PPS. Very rusty with C++, please be gentle.

What am I doing wrong?

Thanks, James.

+1  A: 

You can use the brace syntax only for initialization.

When your constructor is executed, the array member has alredy been created.

Tom
A: 

You can only use curly brace syntax if you're initializing the array at declaration. In your constructor, you're not. You probably want to load map data from a file anyways instead of hard coding.

Donnie
+2  A: 

You can't use array initializers like that in a class constructor. Members can only be initialized by using the initializer list. Your best bet is to load this data from a file, or to declare the array as static.

class Map
{
private:
static int mapArray[15][20];
/* ... */
};

Then define storage for the static array in a source file (.cpp), also known as a translation unit:

int Map::mapArray[15][20] = { ... };
Mads Elvheim
Thanks Mads, for now I'll just make the array static and look into loading it from a file when I get further along. Thanks for your help :D
Jamesz
+3  A: 

You should be able to do something like this:

class Map
{
  int mapArray[15][20];

  public:
  Map() : mapArray( (int[15][20]) {
    { 0,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,197,198,199 },
    { 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219 },
    { 220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 },
    { 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259 },
    { 260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279 },
    { 280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299 }
  } )
  {
  }
};

Note that this initialization style is part of C99 and may not be included with your compiler or may not work for C++. Works on GCC 4 for me.

Also note that I did not compile this code. I adapted it for your case from some other code of mine that does work though.

Zan Lynx
God, that's awful. But correct and useful nonetheless. +1
Mads Elvheim
Is it already decided that compound literals make it into C++0x? Last time I checked compund literals were rejected by C++0x (i could be behind on the latest developments though)
AndreyT
I have used this syntax for years now and even dared to filed bug reports to IDEs which do not recognize it. So far all have fixed it ;-)
drhirsch
This syntax is useful in much more places, in function calls or even with overloaded operators. And as far as I know, this is an extension to serveral compilers (not only gcc). It is one of the points where C99 does implement something useful which C++ doesn't have (another one I am sometimes missing is designated inits). But c++0x will get curly brace constructors, maybe they fill the spot.
drhirsch
@AndreyT: It looks like you are right. This syntax is C99 not C++0x. C++0x is going with a different style, which will also be useful in other situations. I will edit my answer.
Zan Lynx
A: 

Unfortunately, there's no syntax to do literally that in C++ for member non-static arrays. You can assign the initial values to array members one-by-one, but that's, of course, is quite cumbersome.

If the array values are the same in all objects of that class, then you probably need a static member array. See the answer from Mads then.

If you really need a non-static member array, meaning that you want to be able to "customize" the contents of the array on per-object basis by modifying it later or by initializing it differently, then you can try doing this

class Map {
  static const int MapArrayInit[15][20];
  int MapArray[15][20];

public:
  Map() 
  {
    assert(sizeof MapArray == sizeof MapArrayInit); // better: STATIC_ASSERT
    std::memcpy(MapArray, MapArrayInit, sizeof MapArray);
    // Now you can customize MapArray to your liking
  }
};

and in one of the implementation files

const int Map::MapArrayInit = { /* whatever */ };

This will require extra memory for MapArrayInit, but since you are instatiating a separate MapArray in each instance of Map anyway it is not a big deal.

If you don't want to modify your MapArray after initialization but still want to have several different versions of MapArray contents in different instances of `Map', you can use the following approach

class Map {
  static const int MapArrayInit1[15][20];
  static const int MapArrayInit2[15][20];
  static const int MapArrayInit3[15][20];
  const int (&MapArray)[15][20]; // or a pointer

public:
  Map() : MapArray(MapArrayInit1) /* or 2, or 3 */
  {
  }
};

and in one of the implementation files

const int Map::MapArrayInit1 = { /* whatever */ };
const int Map::MapArrayInit2 = { /* whatever */ };
const int Map::MapArrayInit3 = { /* whatever */ };

Choose whatever works best for you.

AndreyT
A: 

This is an assignment, not an initialization. Simple brace initializers only work during initialization. Use the compound literal syntax, which resembles a typecast (to the aggregate you want to initialize) followed by a brace initializer.

Map::Map()
{

    mapArray = (int[15][20]) {
        { 0,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,197,198,199 },
        { 200,201,202,203,204,205,206,207,208,209,210,211,212,213,214,215,216,217,218,219 },
        { 220,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239 },
        { 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259 },
        { 260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279 },
        { 280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299 }
    };    
}
drhirsch