Как передать двумерный массив в качестве аргумента?

мой Matrx класс определяется как

class Matrx
{
 double A[50][50];
 int m,n;
public:
 Matrx(void);
 Matrx(int a, int b)
 {
  m=a;
  n=b;
 }
 Matrx operator +(Matrx b);
 Matrx Transpose(Matrx b);
 Matrx operator *(Matrx b);
 CString printMatrx();
 void readMatrx(double a[][]);
 Matrx TransposeMat(Matrx b);
};

void Matrx::readMatrx(double a[][])
{
 for(int i=0;i< m;i++)
  {
   for(int j=0;j< n;j++)
    A[i][j]=a[i][j];
  }
}

intellisense дает ошибку, как показано ниже

1 IntelliSense: массив может не иметь элементов этого типа d:bmadaptive_dd_v1.02matrx - ... h 17 27 TestServer

почему?

Как передать двумерный массив в качестве аргумента функции?

6 ответов


вам нужно правильно узнать о массивах и указателях. Это включает в себя урок " ха! Они не так полезны, как я думал". После того, как вы познакомились с тем, как работают массивы и указатели, вы должны переосмыслить свой дизайн.

например, на мой взгляд, следующий дизайн имеет много преимуществ:

#ifndef MATRIX_HPP_INCLUDED
#define MATRIX_HPP_INCLUDED

#include <vector>
#include <algorithm>

class matrix
{
public:
    typedef std::vector<double>::size_type st;
    matrix() : rows_(0), cols_(0) {}
    matrix(int r, int c) : rows_(r), cols_(c), coeffs_(st(r)*c,0.0) {}
    void reset(int r, int c)
    { rows_=r; cols_=c; coeffs_.clear(); coeffs_.resize(st(r)*c,0.0); }
    int rows() const {return rows_;}
    int cols() const {return cols_;}
    double const& operator()(int i, int j) const {return coeffs_[indexof(i,j)];}
    double      & operator()(int i, int j)       {return coeffs_[indexof(i,j)];}
    double const* operator[](int i) const {return &coeffs_[indexof(i,0)];}
    double      * operator[](int i)       {return &coeffs_[indexof(i,0)];}
    void swap(matrix& that)
    {
      std::swap(this->rows_,that.rows_);
      std::swap(this->cols_,that.cols_);
      this->coeffs_.swap(that.coeffs_));
    }
private:
    int rows_, cols_;
    std::vector<double> coeffs_;
    st indexof(int i, int j) const {return st(i)*cols+j;} // row major storage
};

inline void swap(matrix& a, matrix& b) {a.swap(b);}

matrix& operator+=(matrix& lhs, matrix const& rhs);
matrix operator+(matrix const& lhs, matrix const& rhs);
matrix operator*(matrix const& lhs, matrix const& rhs);
inline matrix& operator*=(matrix& lhs, matrix const& rhs)
{ matrix tmp = lhs * rhs; swap(tmp,lhs); return lhs; }
...

#endif

таким образом, вы не будете тратить пространство на малые матрицы, и вы можете поддерживать большие матрицы. Кроме того, использование std:: vector вместо a член указатель на динамически выделенную память устраняет необходимость определить свой собственный конструктор копирования, оператор присваивания и деструктор.

конечно, вы можете использовать boost:: multi_array в качестве замены матрицы, но использование пользовательского класса матрицы позволяет объявлять перегруженные операторы в вашем собственном пространстве имен, что желательно из-за ADL (поиск в зависимости от аргумента).

вы можете подумать, что это на самом деле не отвечает на ваш вопрос. В таком случае, позвольте мне подчеркнуть я думаю, вы не совсем понимаете, как работают / ведут себя массивы и указатели. Это то, что вы должны посмотреть в приличной книге на C++. На эту тему можно написать много страниц. Вы не можете ожидать увидеть короткий ответ, объясняющий все причуды.

Проверьте Определенное Руководство По Книге C++ нить.


проблема в том, что при передаче многомерных массивов в качестве параметров в C++, необходимо указать размерность массива внешним. Например:

void ThisIsIllegal(int arr[][]); // Wrong!
void ThisIsAlsoIllegal(int arr[10][]); // Also wrong
void ThisIsLegal(int arr[][10]); // Okay

Если вы хотите иметь функцию, которая принимает массив любого размера, вы можете использовать шаблоны:

template <size_t N, size_t M>
void ThisIsAlsoLegal(int (&arr)[M][N]);

эта последняя версия принимает любой многомерный массив правильного типа и, вероятно, является тем, что вы ищете.


вам нужно указать все, кроме первого измерения, например

void Matrx::readMatrx(double a[][50])

из этого вы должны видеть, что у вас есть фундаментальная проблема с тем, как вы реализовали свой класс, но, по крайней мере, теперь вы должны иметь возможность получить код для компиляции.


вы можете указать все измерения или только последнее измерение для передачи массива:

void Matrx::readMatrx(double a[][50])
{
 for(int i=0;i< m;i++)
  {
   for(int j=0;j< n;j++)
    A[i][j]=a[i][j];
  }
}

спасибо всем вам люди...ты действительно помогал...Я нашел себе новое определение класса и определение функции для матрицы, которая соответствовала моим параметрам. Мне нужен Р комментировать...Ниже приведен пример объявления класса..

#include<iostream>
#include"stdafx.h"
using namespace std;  
const int M=100; const int N=100;  
class Matrix  
{  
    double A[M][N];  
    int m,n;  
public:  
    Matrix(void);  
    Matrix(int a, int b)  
    {  
        m=a;  
        n=b;  
        for(int i=0;i<m;i++)  
        {  
            for(int j=0;j<m;j++)  
                A[i][j]=0.0;  
        }  
    }  
    Matrix operator +(Matrix b);  
    Matrix operator -(Matrix b);  
    Matrix operator *(Matrix b);  
    void TransPose(Matrix b);  
    CString printMatrix();  
    void readMatrix(double*);  
};

а затем реализация функции

#include "stdafx.h"
#include "Matrix.h"

Matrix::Matrix(void)  
{  
}  

Matrix Matrix::operator *(Matrix b)  
{  
 Matrix c(m,m);  
 if(n!=b.m)  
 {  
    HWND hndOwner(0);   
    MessageBoxW(hndOwner,L"Multiplication not possible row and column does not match",L"Error",NULL);  
    Matrix errMat(1,0);  
    double er[1][1]={0}; errMat.readMatrix((double *)er);  
    return errMat;  
 }  
for(int i=0;i< m;i++)  
{  
for(int k=0;k< m;k++)  
{  
c.A[i][k]=0;  
for(int j=0;j< n;j++)  
{  
c.A[i][k] = c.A[i][k]+(A[i][j] * b.A[j][k]) ;  
}  
}  
}  
return c;  
}  
Matrix Matrix::operator +(Matrix b)  
{  
    Matrix c(m,n);  
    if((n!=b.n)||(m!=b.m))  
 {  
    HWND hndOwner(0);   
    MessageBoxW(hndOwner,L"Addition not possible row and column does not match",L"Error",NULL);  
    Matrix errMat(1,0);  
    double er[1][1]={0}; errMat.readMatrix((double *)er);  
    return errMat;  
 }  
    for(int i=0;i<m;i++)  
        {  
            for(int j=0;j< n;j++)  
                {  
                    c.A[i][j]=0.0;  
                }  
        }  
        for(int i=0;i< m;i++)  
        {  
            for(int j=0;j< n;j++)  
                {  
                    c.A[i][j]=A[i][j]+b.A[i][j];  
                }  
        }  
return c;  
}    
CString Matrix::printMatrix()  
{  
    CString strB(" "),strDisp;  
    for(int iRow=0;iRow<m;iRow++)  
    {  
        for(int iColumn=0;iColumn<n;iColumn++)  
        {  
            strB.Format(L"%lf ",A[iRow][iColumn]);  
            strDisp+=strB;  
        }  
            strDisp+="\r\n";  
    }  
        return strDisp;  
}  
void Matrix::readMatrix(double *ptrarr)  
{  
    for(int i=0;i< m;i++)  
        {  
            for(int j=0;j< n;j++)  
                A[i][j]=*(ptrarr+i*n+j);  
        }  
}  
void Matrix::TransPose(Matrix b)  
{  
    for(int i=0;i<b.n;i++)  
    {  
        for(int j=0;j<b.m;j++)  
            A[i][j]=b.A[j][i];  
    }  
}   

простые коды в вышеуказанном работают хорошо до сих пор...если у вас есть предложения по улучшению, пожалуйста, предложить..


вам повезло, потому что:

for(int j=0;j<m;j++)
    A[i][j]=0.0;

наверное, должен быть:

for(int j=0;j<**n**;j++)
    A[i][j]=0.0;