2010-09-15 14 views
19

¿Cómo devuelvo una matriz multidimensional oculta en un campo privado?C++ Regresar matriz multidimensionada de la función

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

........ 

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

no puede convertir int (*)[5][5] a int** en test.cpp retorno/Polky/src línea 73 C/C++ Problema

+4

¿Qué es la grilla? ¿No debería ser 'myarray'? – woodstok

+3

Devolver una referencia directa a un miembro privado puede no ser siempre una buena idea: efectivamente se rompe la encapsulación con esto, permitiendo a cualquier persona acceder y modificar su miembro privado. Esto puede o no ser aceptable en su diseño. –

+0

@MIkhail: Como Justin no ha estado en línea desde el momento en que publicó esta pregunta, me tomé la libertad de solucionarlo. – sbi

Respuesta

-1

Cambiar de su int a int [] [ 's] o intente utilizar int [,] en lugar ?

+1

'int [,]' no es válido C++ –

+3

... y 'int [] []' tampoco deberían ser válidos. En este caso, es importante entender la diferencia entre arrays y punteros. – visitor

+2

@David: en realidad, 'new int [5, 5]' es C++ válido, simplemente no hace lo que uno podría pensar - es lo mismo que 'new int [5]' gracias al operador de coma :) – fredoverflow

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

No. Si usas eso, estarás reinterpretando elementos de la matriz como punteros. –

+0

@Mike Seymour, y eso es cierto si considera que cada fila es int * (como cada vector de enteros que es int *). – rkellerm

4

Para devolver un puntero a la matriz del miembro de la matriz, el tipo necesita es int (*)[5], no int **:

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

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

me las arreglé para hacer este trabajo la función en C++ 0x mediante deducción automática de tipos . Sin embargo, no puedo hacer que funcione sin eso. Las matrices C nativas no se admiten muy bien en C++, su sintaxis es extremadamente horrible. Deberías usar una clase contenedora.

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]; 
} 

Este código compila muy bien. Puede obtener una clase de envoltorio previamente escrita dentro de Boost (boost :: array) que sea compatible con todo el shebang.

+0

No compila con GCC: el primer dato de retorno [índice] hace una referencia no constante de un valor r, dice. – Cubbi

+0

Y ese es el caso, se debe devolver un puntero simple, no una referencia a un puntero. De lo contrario, al menos hemos ganado mucho en legibilidad. Un punto menor: ¿por qué usar 'int' para los tipos de plantilla reales? Algo que no puede ser negativo se expresaría mejor con un tipo entero sin signo, creo. –

+0

datos [índice] es un lvalue, no un valor r, al igual que * ptr es un lvalue. No es que la referencia sea realmente necesaria, creo que es de una versión anterior del código, probablemente podría eliminarla. – Puppy

22

Una matriz bidimensional no decae a un puntero a puntero a ints. Se desintegra a un puntero a matrices de ints, es decir, solo la primera dimensión se desintegra a un puntero. El puntero no apunta a los punteros int, que cuando se incrementan avanzan por el tamaño de un puntero, sino a las matrices de 5 enteros.

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

Un puntero a puntero (int**) se utiliza cuando cada subconjunto se asigna por separado (es decir, que originalmente tiene una matriz de punteros)

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

Aquí tenemos una serie de cinco puntos, cada uno apuntando al primer elemento en un bloque de memoria separado, en total 6 bloques de memoria distintos.

En una matriz bidimensional que presentamos lo mejor un solo bloque contiguo de memoria:

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

debería ver que el diseño de memoria de estas cosas son completamente diferentes, y por lo tanto estas cosas no pueden ser devueltos y pasó la mismo camino.

+0

+1 gracias, gran respuesta –

2

¿Cómo devuelvo una matriz multidimensional oculta en un campo privado?

Si se supone que está oculto, ¿por qué lo devuelve en primer lugar?

De todos modos, no puede devolver matrices de funciones, pero puede devolver un puntero al primer elemento. ¿Cuál es el primer elemento de una matriz de 5x5? Una serie de 5 enteros, por supuesto:

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

Como alternativa, puede devolver toda la matriz por referencia:

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

...bienvenido a la sintaxis del sintetizador C ;-)

¿Puedo sugerir std::vector<std::vector<int> > o boost::multi_array<int, 2> en su lugar?

16

Hay dos tipos posibles que puede devolver para proporcionar acceso a su matriz interna. El antiguo estilo C estaría devolviendo int *[5], ya que la matriz decaerá fácilmente en un puntero al primer elemento, que es del tipo int[5].

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

Ahora, también puede devolver una referencia adecuada a la matriz interna, la sintaxis más simple sería a través de un typedef:

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

O un poco más engorroso sin el typedef:

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

La ventaja de la versión C++ es que se mantiene el tipo real, y eso significa que el tamaño real de la matriz se conoce por el lado de las personas que llaman.

+0

+1 para la versión C++ (con el typedef apropiado) –

+1

Aunque tenga cuidado de cómo usa esos typedefs, a veces: 'delete [] new array5x5()' (parece nuevo, pero es realmente nuevo []). –

Cuestiones relacionadas