2010-02-22 25 views
6

Tengo este problema desde hace bastante tiempo: he arreglado una matriz 2D de tamaño como miembro de la clase.Pasando el puntero a la matriz 2D C++

class myClass 
{ 
public: 
     void getpointeM(...??????...); 
     double * retpointM(); 

private: 

    double M[3][3]; 

}; 

int main() 
{ 
    myClass moo; 
    double *A[3][3]; 

    moo.getpointM(A); ??? 
    A = moo.retpointM(); ??? 

} 

me gustaría pasar puntero a M matriz exterior. Probablemente sea muy simple, pero simplemente no puedo encontrar la combinación adecuada de & y * etc.

Gracias por su ayuda.

Respuesta

9

double *A[3][3]; es una matriz bidimensional de double * s. Quiere double (*A)[3][3]; .

Luego, tenga en cuenta que A y *A y todos tienen la misma dirección, solo diferentes tipos.

Hacer un typedef puede simplificar las cosas:

typedef double d3x3[3][3]; 

Este ser C++, debe pasar la variable por referencia, no el puntero:

void getpointeM(d3x3 &matrix); 

Ahora usted no necesita utilizar parens en escriba nombres y el compilador se asegura de que está pasando una matriz del tamaño correcto.

+0

No debe usar referencias "porque es C++" o "solo porque puede". Úselos cuando sean más claros que las alternativas disponibles. –

+0

@Roger: sí, bueno, es apropiado aquí, de todos modos: v) – Potatoswatter

0

La respuesta corta es que se puede obtener una double * del comienzo de la matriz:

public: 
    double * getMatrix() { return &M[0][0]; } 

Fuera de la clase, sin embargo, realmente no se puede convertir el trivialmente double * en otra matriz 2D directamente, por lo al menos no en un patrón que he visto usado.

puede crear una matriz 2D en el principal, aunque (doble A [3] [3]) y pasar que en a un método GetPoint, lo que podría copiar los valores en la matriz pasada-in. Eso le daría una copia, que podría ser lo que desea (en lugar de los datos originales, modificables). Lo malo es que tienes que copiarlo, por supuesto.

+0

¡No! no te rindas! – Potatoswatter

0

En su función main():

double *A[3][3]; 

crea una matriz 3x3 de double* (o punteros a dobles). En otras palabras, 9 palabras contiguas de memoria de 32 bits para almacenar 9 punteros de memoria.

No es necesario hacer una copia de esta matriz en main() a menos que se destruya la clase, y aún desea tener acceso a esta información. En su lugar, simplemente puede devolver un puntero al inicio de esta matriz de miembros.

Si sólo desea devolver un puntero a un miembro de la clase interna, sólo se necesita realmente un único valor del puntero en main():

double *A; 

Pero, si estás pasando este puntero a una función y se necesitará la función para actualizar su valor, se necesita un puntero doble (lo que permitirá que la función retorne el verdadero valor del puntero de nuevo a la persona que llama:

double **A; 

Y dentro getpointM() puede simplemente punto A al miembro interno (M):

getpointeM(double** A) 
{ 
    // Updated types to make the assignment compatible 
    // This code will make the return argument (A) point to the 
    // memory location (&) of the start of the 2-dimensional array 
    // (M[0][0]). 
    *A = &(M[0][0]); 
} 
+0

bien, parece que eso es lo que realmente quería hacer :) Pero aún con el error: no se puede convertir 'doble [3] [3]' en 'doble *' en la asignación – Moomin

+0

perdón mi error - se olvidó de agregar ** en ambas líneas – Moomin

+2

Esto simplemente no tiene ningún sentido para mí. El miembro se declara como 'doble M [3] [3]'. La asignación '* A = M' simplemente no compilará, porque el lado izquierdo es' doble * 'y el lado derecho es' doble (*) [3] '. Estos tipos no son compatibles. – AnT

0
class myClass 
{ 
public: 
     void getpointeM(double *A[3][3]) 
     { 
      //Initialize array here 
     } 

private: 

    double M[3][3]; 

}; 

int main() 
{ 
    myClass moo; 
    double *A[3][3]; 

    moo.getpointM(A); 
} 
3

Su intención no es clara. ¿Qué se supone que debe hacer getpointeM? ¿Devuelve un puntero a la matriz interna (a través del parámetro) o devuelve una copia de la matriz?

para devolver un puntero, puede hacerlo

// Pointer-based version 
... 
void getpointeM(double (**p)[3][3]) { *p = &M; } 
... 
int main() { 
    double (*A)[3][3]; 
    moo.getpointM(&A); 
} 

// Reference-based version 
... 
void getpointeM(double (*&p)[3][3]) { p = &M; } 
... 
int main() { 
    double (*A)[3][3]; 
    moo.getpointM(A); 
} 

Para retpointM la declaración se vería de la siguiente manera

... 
double (*retpointM())[3][3] { return &M; } 
... 
int main() { 
    double (*A)[3][3]; 
    A = moo.retpointM(); 
} 

Esto es bastante difícil de leer sin embargo. Puede hacer que se vea mucho más claro si se utiliza un nombre de typedef para la matriz de tipo

typedef double M3x3[3][3]; 

En ese caso, los ejemplos anteriores se transformarán en

// Pointer-based version 
... 
void getpointeM(M3x3 **p) { *p = &M; } 
... 
int main() { 
    M3x3 *A; 
    moo.getpointM(&A); 
} 

// Reference-based version 
... 
void getpointeM(M3x3 *&p) { p = &M; } 
... 
int main() { 
    double (*A)[3][3]; 
    moo.getpointM(A); 
} 

// retpointM 
... 
M3x3 *retpointM() { return &M; } 
... 
int main() { 
    M3x3 *A; 
    A = moo.retpointM(); 
} 
0

Es posible que desee tomar el código de su función principal que funciona con la matriz 2D de dobles, y la mueve a myClass como una función miembro. No solo no tendría que lidiar con la dificultad de pasar un puntero para esa matriz 2D, sino que el código externo a su clase ya no necesitaría conocer los detalles de cómo su clase implementa A, ya que ahora llamarían a una función en myClass y dejar que eso haga el trabajo. Si, por ejemplo, luego decidió permitir dimensiones variables de A y eligió reemplazar la matriz con vector de vector s, no necesitaría volver a escribir ningún código de llamada para que funcione.

0

Haz que M sea público en lugar de privado. Como quiera permitir el acceso a M a través de un puntero, M no está encapsulado de todos modos.

struct myClass { 
    myClass() { 
    std::fill_n(&M[0][0], sizeof M/sizeof M[0][0], 0.0); 
    } 
    double M[3][3]; 
}; 

int main() { 
    myClass moo; 
    double (*A)[3] = moo.M; 
    double (&R)[3][3] = moo.M; 

    for (int r = 0; r != 3; ++r) { 
    for (int c = 0; c != 3; ++c) { 
     cout << A[r][c] << R[r][c] << ' '; 
     // notice A[r][c] and R[r][c] are the exact same object 
     // I'm using both to show you can use A and R identically 
    } 
    } 

    return 0; 
} 

Me gustaría, en general, prefieren R sobre A porque el todo de las longitudes están fijos (A podría potencialmente apuntan a una double[10][3] si que era un requisito) y la referencia generalmente conducir a un código más claro.