Getter on multidimensional array

General

Codnpix

4 months ago

Hi, 

I'm stuck with a little problem of multidimensional  array and pointers, and neither of  the answers I found on the internet gave me a working solution for my case... so I ask here. Thanks if anyone has a little tip to give, I'm rather new to C++ :) : 

So this is simple, I have a class containing a 2D array and I want to be able to access it with a getter (returning a pointer of it) :

class Space {
  private:
    char map[10][30];
  public:
    char* getMap();
};

So I have my getter function like this :

char* Space::getLogic() {
  return map;
}

But I always get errors like cannot convert 'char ()[30]' to 'char' in return ...

However this works with a simple array, but not with a multidimensional one. 

I also tried things like that for testing : 

char* Space::test() {
  char* arrPtr;
  char arr[2][5];
  arrPtr = arr;
  return arrPtr;
}

But I always get errors (in that case : cannot convert 'char [2][5]' to 'char*' in assignment)

Anyway, I think I missed something again with how pointers and arrays works... 

I'm really lost here.. thank you for your help :) !

Steph

NEW 4 months ago

In general, by giving direct access to your map, you violate the principle of encapsulation!..... So to avoid.
It is preferable to define read and write accessors to get and set its values.
Then, instead of defining your map by map[10][30] you can define it by map[10*30] which is equivalent.
Here is a small example that answers your problem:

// --------------------------
// Space.h
// --------------------------

#include <Gamebuino-Meta.h>

class Space
{
    private:

        char* map;

    public:

        static const uint8_t ROWS;
        static const uint8_t COLS;

        Space();
        ~Space();

        char getMap(uint8_t i, uint8_t j);
        void setMap(uint8_t i, uint8_t j, char value);
};

// --------------------------
// Space.cpp
// --------------------------

#include <Gamebuino-Meta.h>
#include "Space.h"

const uint8_t Space::ROWS = 4;
const uint8_t Space::COLS = 5;

Space::Space() {
    this->map = new char[ROWS*COLS];
}

Space::~Space() {
    delete[] this->map;
}

char Space::getMap(uint8_t i, uint8_t j) {
    return this->map[i * COLS + j];
}

void Space::setMap(uint8_t i, uint8_t j, char value) {
    this->map[i * COLS + j] = value;
}

// --------------------------
// Sketch.ino
// --------------------------

#include <Gamebuino-Meta.h>
#include "Space.h"

uint8_t i,j;
Space space;

void setup() {
    gb.begin();
    SerialUSB.begin(9600);

    for (i = 0; i < Space::ROWS; i++) {
        for (j = 0; j < Space::COLS; j++) {
            space.setMap(i, j, 'a' + random(0,26));
        }
    }
}

void loop() {
    while (!gb.update());

    for (i = 0; i < Space::ROWS; i++) {
        for (j = 0; j < Space::COLS; j++) {
            SerialUSB.printf("%c ", space.getMap(i,j));
        }
        SerialUSB.println();
    }
    SerialUSB.println();
}

Is that clearer?

Codnpix

NEW 4 months ago

In general, by giving direct access to your map, you violate the principle of encapsulation!..... So to avoid.

But I thought that was precisely what I was trying to avoid, by keeping my map as a private attribute and writing a getter to return a pointer to it, so it wasn't it?

Anyway yes it's clearer that way, I see that it's cleaner to retrieve the values of the array one by one instead of giving the whole reference. So the getter is returning a copy of the given array index value each time it's called and not the reference of the actual data, is that it ? (and maybe that's why you said I was trying to give a direct access to the array ?).

I think I understand better. Thank you for your patience :)! 

I believe I have a few changes to make all over my code then...^^.

Steph

4 months ago

But I thought that was precisely what I was trying to avoid, by keeping my map as a private attribute and writing a getter to return a pointer to it, so it wasn't it?

By returning a pointer to your map, you transmit precisely the address in memory of the corresponding data structure... In other words, you open the door that was closed by the private specifier access!

So the getter is returning a copy of the given array index value each time it's called and not the reference of the actual data, is that it ?

Precisely :-)

Steph

NEW 4 months ago

Codnpix Codnpix

But I thought that was precisely what I was trying to avoid, by keeping my map as a private attribute and writing a getter to return a pointer to it, so it wasn't it?

By returning a pointer to your map, you transmit precisely the address in memory of the corresponding data structure... In other words, you open the door that was closed by the private specifier access!

So the getter is returning a copy of the given array index value each time it's called and not the reference of the actual data, is that it ?

Precisely :-)