2010-09-15 16 views
19

Jak zwrócić tablicę wielowymiarową ukrytą w polu prywatnym?C++ Powracająca macierz wielowymiarowa z funkcji

class Myclass { 
private: 
int myarray[5][5]; 
public: 
int **get_array(); 
}; 

........ 

int **Myclass::get_array() { 
return myarray; 
} 

nie może konwertować int (*)[5][5] do int** w zamian test.cpp/Polky/src linia 73 C/C++ Problem

+4

co to jest siatka? czy nie powinno to być 'myarray'? – woodstok

+3

Zwrot bezpośredni do prywatnego członka nie zawsze jest dobrym pomysłem - skutecznie przełamujesz hermetyzację, umożliwiając każdemu dostęp i modyfikowanie Twojego prywatnego członka. To może, ale nie musi być dopuszczalne w twoim projekcie. –

+0

@MIkhail: Ponieważ Justin nie był online od momentu, w którym opublikował to pytanie, skorzystałem z prawa, aby to naprawić. – sbi

Odpowiedz

-1

Zmień swoją int do int [] [] 's lub spróbuj użyć int [,] zamiast ?

+1

'int [,]' nie jest poprawny C++ –

+3

... i 'int [] []' nie powinno być ważne. W takim przypadku ważne jest, aby zrozumieć różnicę między tablicami a wskaźnikami. – visitor

+2

@David: Właściwie, 'new int [5, 5]' jest poprawny C++, po prostu nie robi tego, co mogłoby się wydawać - jest takie samo jak 'new int [5]' dzięki operatorowi przecinka :) – fredoverflow

-1
int **Myclass::get_array() { 
return (int**)myarray; 
} 
+1

Nie. Jeśli użyjesz tego, będziesz reinterpretować elementy tablicy jako wskaźniki. –

+0

@Mike Seymour, i to prawda, jeśli każdy wiersz będzie int * (jak każdy wektor liczb całkowitych, które jest int *). – rkellerm

4

Aby powrócić wskaźnik do macierzy członka macierzy, typ potrzebna jest int (*)[5] nie int **:

class Myclass { 
private: 
    int myarray[5][5]; 
public: 
    int (*get_array())[5]; 
}; 

int (*Myclass::get_array())[5] { 
    return myarray; 
} 
1

udało mi się zrobić tę pracę funkcji w C++ 0x użyciu automatycznego typu odliczenie . Jednak nie mogę sprawić, by działał bez tego. Macierzyste tablice C nie są bardzo dobrze obsługiwane w C++ - ich składnia jest wyjątkowo ohydna. Powinieneś użyć klasy opakowania.

template<typename T, int firstdim, int seconddim> class TwoDimensionalArray { 
    T data[firstdim][seconddim]; 
public: 
    T*& operator[](int index) { 
     return data[index]; 
    } 
    const T*& operator[](int index) const { 
     return data[index]; 
    } 
}; 
class Myclass { 
public: 
    typedef TwoDimensionalArray<int, 5, 5> arraytype; 
private: 
    arraytype myarray; 
public: 
    arraytype& get_array() { 
     return myarray; 
    } 
}; 

int main(int argc, char **argv) { 
    Myclass m; 
    Myclass::arraytype& var = m.get_array(); 
    int& someint = var[0][0]; 
} 

Ten kod jest kompilowany poprawnie. Możesz dostać wstępnie napisaną klasę wewnątrz Boost (boost :: array), która obsługuje cały shebang.

+0

Nie kompiluje się z GCC: pierwsze dane zwracane [indeks] tworzy niezwiązane odwołanie z wartości r, mówi. – Cubbi

+0

I tak jest w przypadku, zwracany jest czysty wskaźnik, a nie odnośnik do wskaźnika. W przeciwnym razie przynajmniej zyskujemy dużo na czytelności. Jeden mały punkt: po co używać 'int' dla rzeczywistych typów szablonów? Coś, co nie może być ujemne, byłoby lepiej wyrażone za pomocą typu liczb całkowitych bez znaku. –

+0

dane [indeks] jest lwartością, a nie rwartością, podobnie jak * ptr jest lwartością. Nie chodzi o to, że odniesienie jest naprawdę konieczne, myślę, że pochodzi ono z poprzedniej wersji kodu, prawdopodobnie można go usunąć. – Puppy

22

Tablica dwuwymiarowa nie rozpada się na wskaźnik do wskaźnika na ints. Rozpada się na wskaźnik do tablic int - to znaczy, że tylko pierwszy wymiar rozpada się na wskaźnik. Wskaźnik nie wskazuje na wskaźniki int, które po inkrementacji przesuwają się o wielkość wskaźnika, ale do tablic z 5 liczbami całkowitymi.

class Myclass { 
private: 
    int myarray[5][5]; 
public: 
    typedef int (*pointer_to_arrays)[5]; //typedefs can make things more readable with such awkward types 

    pointer_to_arrays get_array() {return myarray;} 
}; 

int main() 
{ 
    Myclass o; 
    int (*a)[5] = o.get_array(); 
    //or 
    Myclass::pointer_to_arrays b = o.get_array(); 
} 

wskaźnik do wskaźnika (int**) stosuje się, gdy każdy subarray przeznaczono oddzielnie (to znaczy, że pierwotnie miał tablicę wskaźników)

int* p[5]; 
for (int i = 0; i != 5; ++i) { 
    p[i] = new int[5]; 
} 

Tutaj mamy tablicę pięciu wskaźników, każdy wskazuje na pierwszy element w osobnym bloku pamięci, łącznie 6 różnych bloków pamięci.

W dwuwymiarowej tablicy można uzyskać pojedynczy ciągły blok pamięci:

int arr[5][5]; //a single block of 5 * 5 * sizeof(int) bytes 

Należy zauważyć, że układ pamięci te rzeczy są zupełnie inne, a więc te rzeczy nie mogą być zwrócone i przeszedł ta sama droga.

+0

+1 dziękuję, świetna odpowiedź –

2

Jak mogę zwrócić tablicę wielowymiarową ukrytą w prywatnym polu?

Jeśli to ma być ukryte, dlaczego zwracasz je w pierwszej kolejności?

W każdym razie nie można zwrócić tablic z funkcji, ale można zwrócić wskaźnik do pierwszego elementu. Jaki jest pierwszy element tablicy int 5x5? Tablica 5 wskazówki, oczywiście:

int (*get_grid())[5] 
{ 
    return grid; 
} 

Alternatywnie, można zwrócić całą tablicę przez odniesienie:

int (&get_grid())[5][5] 
{ 
    return grid; 
} 

...witamy w piekle składni deklaratora C ;-)

Czy mogę zamiast tego zaproponować std::vector<std::vector<int> > lub boost::multi_array<int, 2>?

16

Istnieją dwa możliwe typy, które można zwrócić, aby zapewnić dostęp do wewnętrznej tablicy. Stary styl w stylu C będzie zwracał int *[5], ponieważ tablica będzie łatwo zanikać do wskaźnika do pierwszego elementu, który jest typu int[5].

int (*foo())[5] { 
    static int array[5][5] = {}; 
    return array; 
} 

Teraz można również powrócić do właściwego odniesienia do tablicy wewnętrznej, najprostszy składnia byłoby przez typedef:

typedef int (&array5x5)[5][5]; 
array5x5 foo() { 
    static int array[5][5] = {}; 
    return array; 
} 

lub nieco bardziej kłopotliwe bez typedef:

int (&foo())[5][5] { 
    static int array[5][5] = {}; 
    return array; 
} 

Zaletą wersji C++ jest fakt, że rzeczywisty typ jest utrzymywany, a to oznacza, że ​​rzeczywisty rozmiar tablicy jest znany po stronie dzwoniących.

+0

+1 dla wersji C++ (z właściwym typedef) –

+1

Chociaż należy uważać, jak używać tych typów, czasami: 'delete [] new array5x5()' (wygląda jak nowy, ale jest naprawdę nowy []). –

Powiązane problemy