Evan
Evan

Reputation: 167

Error while accessing dynamically allocated array between classes

UPDATE: Most of my relevant source code is in this pastebin: http://pastebin.com/nhAx1jfG

Can anyone make sense of this error? I'm trying to access a 2d "Tile" array I declare in a different class in the same namespace, it's public, and I do declare an object in the main "rouge.cpp" class.

g++ -Wall -Werror -lncurses -c rouge.cpp -o rouge.o
rouge.cpp: In function ‘void update_game(Player, Map, World, bool)’:
rouge.cpp:497: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((((unsigned int)player.Player::<anonymous>.GameObject::x) + 0xffffffffffffffffffffffffffffffffu) * 16u))[player.Player::<anonymous>.GameObject::y]’
rouge.cpp:506: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((((unsigned int)player.Player::<anonymous>.GameObject::x) + 1u) * 16u))[player.Player::<anonymous>.GameObject::y]’
rouge.cpp:515: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((unsigned int)(((unsigned int)player.Player::<anonymous>.GameObject::x) * 16u)))[(player.Player::<anonymous>.GameObject::y + -0x00000000000000001)]’
rouge.cpp:524: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((unsigned int)(((unsigned int)player.Player::<anonymous>.GameObject::x) * 16u)))[(player.Player::<anonymous>.GameObject::y + 1)]’
rouge.cpp:540: error: no match for ‘operator[]’ in ‘*(world.World::tiles + ((unsigned int)(((unsigned int)player.Player::<anonymous>.GameObject::x) * 16u)))[player.Player::<anonymous>.GameObject::y]’
make: *** [rouge.o] Error 1

world.h:

// The "world" class, generates a world.
class World
{
    // Public classes and variables
    public:
        // Tile array
        Tile* tiles;
        int plates[WORLDSIZEX][WORLDSIZEY];
        //Tile tiles[WORLDSIZEX][WORLDSIZEY];
        //Tile (*tiles)[WORLDSIZEX] = new Tile[WORLDSIZEX][WORLDSIZEY];
        // For plates
        //int plates[WORLDSIZEX][WORLDSIZEY];
        //plates = new int[WORLDSIZEX][WORLDSIZEY];
        //int (*plates)[WORLDSIZEX] = new int[WORLDSIZEX][WORLDSIZEY];
        // Small world
        Tile smalltiles[SMALLWORLDX][SMALLWORLDY];
        // For world temp
        int worldtemp;
        // Constructor
        World();
        void generate_plates();
        bool check_plates();
        int build_mountains(int,int);
        void add_mountains();
        void generate_world();
        void shrink_world();
        void save_world();
        void erupt();
        bool get_passable(int,int);
        char get_icon(int,int);
        char get_small_icon(int,int);
        int get_color(int,int);
        int get_small_color(int,int);
};

world.cpp where I allocate the array:

// Constructor
World::World()
{
    // Seed for random number
    srand( time(NULL) );
    tiles = new Tile[WORLDSIZEX][WORLDSIZEY];
    // Generate a world
    generate_world();
    // Shrink world
    shrink_world();
    // Then save it.
    //save_world();
}

in rouge.cpp, I access it just like:

world.tiles[i][j]; //i and j are ints in a nested for loop

after I declare it like:

World world;

and it's spitting out that error

Upvotes: 2

Views: 1133

Answers (3)

Emile Cormier
Emile Cormier

Reputation: 29209

You're using a pointer to point to an array that was dynamically allocated as a multidimensional array. After the address of this multidimensional array is stored in World::tiles, the compiler "forgets" that the array was multidimensional. Thus, you can no longer use the double brackets notation (tiles[x][y]) to access an element.

To get around this, you have at least 4 options:

  1. Provide a method in World that takes x,y coordinates and returns a reference to the desired cell (you might want to provide both const and non-const versions):

    Tile& at(size_t x, size_t y) {return tiles[y*WORLDSIZEX + x];}

    const Tile& at(size_t x, size_t y) const {return tiles[y*WORLDSIZEX + x];}

  2. Roll-up your own 2D array class for World::tiles.

  3. Use a boost::multi_array for World::tiles.

  4. Declare World::tiles as vector< vector<Tile> >. The initial sizing of all nested vectors is tricky, but after that you can use the world.tiles[x][y] notation.

Plus the option @fsmc gave you.


I took a quick look at your code in the pastebin. It would be much more efficient (and cleaner looking) if you initialized your tiles vectors like this instead:

tiles.resize(WORLDSIZEX);
for(int i = 0; i < WORLDSIZEX; i++)
{
    tiles[i].resize(WORLDSIZEY);
}

Upvotes: 2

Michael Chinen
Michael Chinen

Reputation: 18697

world.tiles is of type Tile*. It is the wrong type to be a two dimensional array (you would need Tile**, and need to initialize it in two steps (one to create an array of Tile* pointers, and a loop to create an array that each of those Tile * pointers can point to.

e.g. in your class def:

Tile **tiles

e.g.: in your constructor:

tiles = new Tile*[SMALLWORLDX];
for (int i = 0; i < SMALLWORLDX; i++)
   tiles[i] = new Tile[SMALLWORLDY];

So getting back to what was causing your original error- when you were calling world.tiles[x][y], the first [] operator was okay, because tiles could be pointing to an array of Tiles, but the second one is not okay.

Upvotes: 2

Nathanael
Nathanael

Reputation: 1772

Just based on the error message, whatever you are trying to index is not actually an array. The '*' (dereference) operator at the beginning of that statement looks suspicious to me, but without actually seeing your code I can't say much else.

Upvotes: 0

Related Questions