Ошибка при доступе к динамически распределенному массиву между классами - PullRequest
2 голосов
/ 15 апреля 2011

ОБНОВЛЕНИЕ: Большая часть моего соответствующего исходного кода находится в этом виде: http://pastebin.com/nhAx1jfG

Может кто-нибудь понять смысл этой ошибки?Я пытаюсь получить доступ к двумерному массиву "Tile", который я объявляю в другом классе в том же пространстве имен, он общедоступен, и я объявляю объект в основном классе "rouge.cpp".

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, где я размещаю массив:

// 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();
}

в rouge.cpp, я обращаюсь к нему так же, как:

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

после того, как я объявил это как:

World world;

и он выплевывает эту ошибку

Ответы [ 3 ]

2 голосов
/ 15 апреля 2011

world.tiles относится к типу плитки *.Это неправильный тип, чтобы быть двумерным массивом (вам потребуется Tile**, и вам нужно инициализировать его в два этапа (один для создания массива Tile* указателей и цикл для создания массива, каждый из которыхTile * указатели могут указывать на.

например, в вашем классе def:

Tile **tiles

например: в вашем конструкторе:

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

Итак, возвращаясь к тому, что быловызывая исходную ошибку - когда вы вызывали world.tiles[x][y], первый оператор [] был в порядке, потому что плитки могли указывать на массив Tiles, но второй не в порядке.

2 голосов
/ 15 апреля 2011

Вы используете указатель для указания на массив, который был динамически выделен как многомерный массив.После сохранения адреса этого многомерного массива в World::tiles компилятор «забывает», что массив был многомерным.Таким образом, вы больше не можете использовать двойные скобки (tiles[x][y]) для доступа к элементу.

Чтобы обойти это, у вас есть как минимум 4 варианта:

  1. Предоставьте метод в World, который принимает координаты x, y и возвращает ссылку на нужную ячейку (вы можете предоставить как постоянную, так и неконстантную версии):

    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. Сверните свой собственный класс двумерного массива для World::tiles.

  3. Используйте boost :: multi_array для World::tiles.

  4. Объявить World::tiles как vector< vector<Tile> >.Первоначальный размер всех вложенных векторов сложен, но после этого вы можете использовать нотацию world.tiles[x][y].

Плюс опция @fsmc предоставила вам.


Я быстро взглянул на твой код в пастбине.Было бы намного эффективнее (и выглядело чище), если бы вместо этого вы инициализировали свои tiles векторы:

tiles.resize(WORLDSIZEX);
for(int i = 0; i < WORLDSIZEX; i++)
{
    tiles[i].resize(WORLDSIZEY);
}
0 голосов
/ 15 апреля 2011

На основании сообщения об ошибке все, что вы пытаетесь проиндексировать, на самом деле не является массивом.Оператор '*' (разыменование) в начале этого оператора кажется мне подозрительным, но, фактически, не видя ваш код, я больше ничего не могу сказать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...