2011-01-26 4 views
9

Мой 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.02 \ matrx.h 17 27 TestServer

Почему?

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

+3

Пока код, который вы представляете, недопустим, C++, не полагайтесь на Intellisense для поиска синтаксических ошибок. Intellisense - это инструмент автозаполнения, а не средство проверки синтаксиса. Он только «быстро смотрит» на ваш код и не может давать наиболее точные сообщения об ошибках. Вместо этого вы должны попытаться скомпилировать его (с фактическим компилятором, конечно) и опубликовать фактическое сообщение об ошибке компилятора (ов), если оно есть. –

+3

Я уверен, что вокруг этого много дубликатов и вопросов. Найдите в поле выше для '[C++] двумерный массив или аналогичный и перейдите по различным вопросам/ответам. Даже если они не совсем то же самое, они, несомненно, предоставят некоторое представление. –

ответ

4

Вам необходимо правильно узнать о массивах и указателях. Это включает в себя урок: «Да, они не так полезны, как я думал». После того, как вы знакомы с тем, как работают массивы и указатели, вы должны пересмотреть свой дизайн.

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

#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 вместо элемента указателя, указывающего на динамически выделенную память, устраняет необходимость в определении собственного конструктора копирования, оператора присваивания и деструктора.

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

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

Проверьте резьбу Definite C++ Book Guide.

+0

спасибо sellibitze ... вы правы ... Пожалуйста, скажите мне, если мне нужно перегрузить +, *, /, - мне нужно написать функции перегрузки отдельно, как я это делал раньше? Если да, пожалуйста, сообщите объявление в классе, который вы предоставили ... – user543265

+0

Кроме того, вместо переопределения предпочтительным является использование чего-то стандартного типа 'boost :: multi_array'. – Kos

+0

sellibitze, можете ли вы рассказать мне, есть ли какой-либо специальный заголовочный файл, который мне нужно включить, помимо iostream.h, и помимо написания с использованием namspace std; потому что я получаю сообщение об ошибке, как \t \t 15 IntelliSense: Пространство имен "станд" не имеет ни один член "вектор" \t d: \ bmadaptive_dd_v1.02 \ matrx.h \t TestServer – user543265

1

Необходимо указать все, кроме первого измерения, например.

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

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

+0

Спасибо, Пол .... Он работал, но теперь появляется сообщение об ошибке вроде этого. \t \t 5 IntelliSense: аргумент типа "двойной (*) [4]" несовместимо с параметром типа "двойной (*) [50]" \t д: \ bmadaptive_dd_v1.02 \ testserverdlg.cpp \t \t 19 тысячи сорок-одна \t TestServer для кода double X [15] [4], splusn [15], m_dC = 1.0, y [15], W [15] [4], WTrans [4] [15]; \t Matrx Wtest (15,4), WtestTrans (4,15); \t для (INT R = 0; г <15; г ++) { \t \t для (целое д = 0; д <4; д ++) \t \t Ш [г] [Q] = 0,1; \t \t Wtest.readMatrx (W); \t} – user543265

+3

@ user543265: Запись ошибки компилятора без кода, в котором флагов компилятора не слишком полезен. Выполнение этого комментария делает его еще труднее читать. Либо обновите вопрос, добавив это до конца, либо создайте отдельный вопрос. Любой из них облегчит людям помощь. –

25

Проблема заключается в том, что при передаче многомерных массивов в качестве параметров в 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]); 

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

+2

класс Matrx {---------------------- template void readMatrx (double (& a) [M] [N]); Matrx TransposeMat (Matrx b); }; Я изменил свой класс таким образом, и моя функция вроде шаблона void Matrx :: readMatrx (double a [M] [N]) { \t для (int i = 0; i user543265

+2

«... вы должны указать все, кроме самого внутреннего измерения», чтобы обобщить на все массивы (включая одно измерение), но в противном случае это тоже будет предлагать IISAlsoLegal. –

+0

@ user543265- Вы обновили объявление функции в теле класса? – templatetypedef

0

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

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

Вы не можете передать двумерный массив в качестве указателя на указатель. Многомерные массивы - это * не * массивы указателей! –

+0

Это распространенная ошибка. Двумерный массив является непрерывным блоком памяти, в котором все элементы первой строки следуют за второй строкой и так далее. Если двумерный массив распадается, он делает это путем преобразования в указатель на первый элемент, который будет «массивом из N элементов типа T», а не «указателем на T». Пока перед доступом к массиву * row * он снова распадается на указатель, второй указатель будет иметь адрес массива. То есть: '& array',' & array [0] 'и' & array [0] [0] '- это тот же адрес. –

+0

С другой стороны, с указателем на указатель на T' массив первого сохраненного элемента будет результатом разыменования первого указателя 'p [0]', интерпретирующего это как указатель и разыменование снова '(p [0]) [0] ', и если он не был инициализирован собственным адресом, он будет отличаться от' & p [0] [0] ' –

0

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

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

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

-1

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

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

должно быть:

for(int j=0;j<**n**;j++) 
    A[i][j]=0.0; 
Смежные вопросы