1

I am trying to take 2D array of objects of my custom class hexTile, and pass them through a function, and using a member function on a specific part of the 2D array. Here is my main.cpp file:

int main(int argc, const char * argv[]) {
    static int tile_count=32;

    //To make the initial map
    hexTile tilemap [32][32];

    for(int i=0; i<tile_count; i++ ){
        for(int j=0; j<tile_count; j++ ){
            tilemap[i][j].makeEmpty();
            tilemap[i][j].makeColumnCoordinate(i);
            tilemap[i][j].makeRowCoordinate(j);
            tilemap[i][j].update_onTile(false, false, false, false);
        }
    }

    return 0;
}

void makeCityTile(hexTile (*map)[32][32], int tile_count){
    int center=tile_count/2;
    *map[center][center].makeExists();
}

When I try to compile this code, on the line *map[center][center].makeExists();, I get an error Member reference base type 'hexTile [32]' is not a structure or union. This doesn't make much sense because I have defined .makeExists in tile_class.hpp and tile_class.cpp.

1 Answers1

0

It's because of the operator precedence: *map[center][center].makeExists() is equal to *(map[center][center].makeExists()), but you meant (*map)[center][center].makeExists(). However, you should just write the following:

void makeCityTile(hexTile map[32][32], int tile_count) {
    int center=tile_count/2;
    map[center][center].makeExists();
}

This is because in C and C++, when you pass an array to a function, it only passes a pointer to that array, it doesn't pass a copy of the whole array by value. See What is array decaying? for more details.

To avoid confusion, it might be helpful to create a class to represent a map, and add member functions to manipulate that map. And while you are at it, C++ provides std::vector<> which is usually a much nicer way to store an array. Here's a quick example of how that might look:

class Map {
    const size_t count;
    std::vector<hexTile> tiles;

    public:
    Map(size_t count): count(count), tiles(count * count) {
        // put the initialization code from your main() here
    }
    hexTile &at(size_t x, size_t y) {
        return &tiles[y * count + x];
    }
    void makeCityTile() {
        at(count / 2, count / 2).makeExists();
    }
    ...
};
G. Sliepen
  • 7,637
  • 1
  • 15
  • 31
  • Re "`*(map[center][center].makeExists()), but you meant (*map[center][center]).makeExists()`": No, the OP meant `(*map)[center][center].makeExists()`. Use and declaration are alike, with the exception of references. – Peter - Reinstate Monica Oct 12 '19 at 17:40
  • Also the statement "arrays are normally passed by reference" is misleading. You are correct from a logical standpoint because the array is not copied; but in C and C++ parameter passing is *by value* unless passing by reference is explicitly declared in C++. What's passed *by value* here is a pointer to the first element of the array (the element being a `hextile[32]`), to which an array argument is adjusted when passed. – Peter - Reinstate Monica Oct 12 '19 at 17:46
  • @PeterA.Schneider You are correct, although saying that when you declare `int foo[10]` that `foo` is just a pointer to the first element of that array, is also not entirely correct. It decays to a pointer at some point. I'm afraid I don't know of a good way to word this which is strictly correct and which is intuitive for beginners. – G. Sliepen Oct 12 '19 at 17:55
  • Edited to let my betters on StackOverflow do the explaining. – G. Sliepen Oct 12 '19 at 18:09
  • No no, `foo` is an `int[10]`. It is *"adjusted"* to a pointer when passed as an argument, see the ISO C standard draft, par. 6.7.5.3/7 and 6.9.1/10, here: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf – Peter - Reinstate Monica Oct 12 '19 at 19:36
  • 1
    You are still having it wrong, and it's annoying because it may confuse readers. The OP's declaration `void makeCityTile(hexTile (*map)[32][32], int tile_count)` indicates that `map` is **a pointer to an array of `hexTile` with the dimensions 32x32.** One cannot pass the address of an array with different dimensions. It **does not** indicate that `map` is an array of pointers *at all!* One calls it with `hexTile tilemap [32][32]; makeCityTile(&tilemap);`. The function's code must use `(*map)[i][j].memberFunction();`, that is, it must first *dereference* the pointer to obtain the array. – Peter - Reinstate Monica Oct 12 '19 at 22:39