wskaźnik do tablicy wielowymiarowej w klasie -> odwołanie

0

Cześć!
napisałem sobie następującą klasę:

	class klasa
		{
		public:
			double *** tab;
			void fun(int a, int b, int c);
			klasa::klasa(){};
		protected:
			int x;
			int y;
			int z;
		};
	void klasa::fun(int a, int b, int c)
		{
		x = a;
		y = b;
		z = c;
		int i,j;
		tab = new double**[x];
		for(i=0; i<x; i++)
			{
			tab[i] = new double*[y];
			for(j=0; j<y; j++)
				tab[i][j] = new double[z];
			}
		}

Wszystko działa jak należy. Niestety ten wskaźnik dla bezpieczeństwa powinien być protected! No i pytanie teraz: jak napisać funkcję, która będzie się odwoływać do tego wskaźnika tak jakby się odwoływało do zwykłej tablicy (z operatorem [][][]) -> tj. jak przeciążyć taki operator?
Obecnie odwołuję się do tego obiektu tak:
klasa obiekt;
obiekt.fun(3,4,5);
obiekt.tab[x][y][z];
chciałbym identycznie tylko żeby tab była funkcją, która przy okazji sprawdza czy podany parametr nie jest większy od x/y/z zapisanego w klasie w miejscu protected.

Z góry dziękuję za pomoc!

0

Nie czasu się głęboko zastanawiać, ale tak powinno zadziałać:

double ** operator[](int index)
{
   return tab[index];
}

EDIT: hmm jednak nie pomoże Tobie zbytnio, bo sprawdzisz tylko czy x nie wykracza poza zakres...

Proponuję użyć zamiast tablic klasy Vector, albo napisać własną klasę opakowującą tablicę i znającą jej rozmiar

0

W sensie - chcesz się odwoływać tak obiekt[x][y][z]? Trzeba przeładować operator [] dla tej klasy, która zwróci proxy z przeładowanym operatorem [], która zwróci jeszcze jeden obiekt proxy z ostatecznie przeładowanym operatorem [].

Wydaje mi się, że jest na forum kawałek kodu z czymś podobnym. Możesz też w google szukać pod keywordami "multiple subscript" czy "proxy pattern, subscript".

Tak szczerze? Lepiej będzie jak przygotujesz dwie, zwykłe metody, które będą zwracać i przyjmować wartości na podstawie indeksów, które będą zwykłymi argumentami.

0

A dlaczego nie przeciążyć operatora ()? Na przykład w taki sposób:

class klasa
{
public:
    // ...
    double& operator()(int x_, int y_, int z_);
    double operator()(int x_, int y_, int z_) const;
    // ...
    
protected:
    int x;
    int y;
    int z;
    double*** tab;
};

double& klasa::operator()(int x_, int y_, int z_) {
    assert(x_ >= 0 && x_ < x);
    assert(y_ >= 0 && y_ < y);
    assert(z_ >= 0 && z_ < z);
    return tab[x][y][z];
}

double klasa::operator()(int x_, int y_, int z_) const {
    return this->operator()(x_, y_, z_);
}

int main() {
    klasa k;
    
    // inicjalizacja, etc.
    
    cout << k(1, 2, 3) << endl;
    k(3, 4, 5) = 3.14;
}
0

Dzięki. Poszperam jeszcze, ale póki co ciężko.
Jeśli chodzi o wywołanie to bardziej myślałem, żeby zamiast wywoływać funkcję tak: obiekt.fun2(3,4,5) można było zrobić tak: obiekt.fun2[3][4][5] -> zadaniem tej funkcji byłoby tylko odwołanie się do elementu tablicy do której wskaźnik byłby protected.

0

@Rev, czy chodziło Ci o ten wątek: http://4programmers.net/Forum/C_i_C++/121315-Cpp_przeciazenie_operatora ? :)
Mam identyczny problem tylko dot. tablicy 3d a nie 2d!

Niestety nie za bardzo to rozumiem -.-
Tak analogicznie to chyba by wyglądało w ten sposób:

double** operator[](int i){return tab[i];};
double* operator[](int i){return tab[i];};

Ale to nie działa - i w sumie tego nie rozumiem :/

Czy mógłby mi ktoś z tym pomóc - z góry dziękuję!

0

Nie.

Załóżmy, że mamy klasę KolekcjaKsiążek. Ma ona przeładowany operator [], który zwraca nam obiekt klasy Książka. Ta klasa z kolei ma przeładowany operator [], który zwraca nam obiekt klasy Rozdział. Ta klasa ma w końcu przeładowany operator [], który zwraca obiekt klasy Wiersz (linia). Jeżeli chcemy zmienić pierwszą linię z trzeciego rozdziału naszej piątej książki, zrobimy: kolekcja[4][2][0] = "nowa linia";. Musisz wprowadzić teraz identyczną strukturę do swojego programu. Jak widzisz - jest to dość upierdliwe, tak na dobrą sprawę przy każdym dostępie musisz tworzyć dwa dodatkowe obiekty.

0

No tak, ale czy nie można przeładować trzykrotnie operatora [] w ten sposób, że jeden operator będzie przyjmować jako argument zwykłą zmienną i będzie zwracać wskaźnik do najbardziej zewnętrznego wymiaru tj. tab[][][tu].
drugie przeładowanie będzie przyjmować jako argument wskaźnik i będzie zwracać wskaźnik do wskaźnika tj. tab[][tu][]
trzecie przeładowanie jako argument będzie przyjmować wskaźnik do wskaźnika do wskaźnika (***) i zwracać będzie również wskaźnik do ... czyli tab[tu][][]

1 użytkowników online, w tym zalogowanych: 0, gości: 1