简体   繁体   中英

operator overloading [][] 2d array c++

I have a 2D array and I want to define a function that returns the value of the index that the user gives me using operator overloading. In other words:

void MyMatrix::ReturnValue()
{
    int row = 0, col = 0;
    cout << "Return Value From the last Matrix" << endl;
    cout << "----------------------------------" << endl;
    cout << "Please Enter the index: [" << row << "][" << col << "] =" << ((*this).matrix)[row][col] << endl;
}

The operation ((*this).matrix)[row][col] should return an int . I have no idea how to build the operator [][] .
Alternatively, I could concatenate a couple of calls to the operator [] , but I didn't succeed in it, because the first call to that operaror will return int* and the second one will return int , and it compel to build another operator, and I dont want to do that.

The data matrix is defined like

int** matrix; matrix = new int*[row];
if (matrix == NULL)
{
    cout << "Allocation memory - Failed";
}
for (int i = 0; i < row; i++)//Allocation memory
{
    matrix[i] = new int[col];
    if (matrix[i] == NULL)
    {
        cout << "Allocation memory - Failed";
        return;
    }
}

What can I do? Thank you,

Simply, such an operator does not exist , so you can not overload it.

A possible solution is to define two classes: the Matrix and the Row .
You can define the operator[] of a Matrix so that it returns a Row , then define the same operator for the Row so that it returns an actual value ( int or whatever you want, your Matrix could be also a template).
This way, the statement myMatrix[row][col] will be legal and meaningful.

The same can be done in order to assign a new Row to a Matrix or to change a value in a Row .

* EDIT *

As suggested in the comments, also you should take in consideration to use operator() instead of operator[] for such a case.
This way, there wouldn't be anymore the need for a Row class too.

You can define your own operator [] for the class. A straightforward approach can look the following way

#include <iostream>
#include <iomanip>

struct A
{
    enum { Rows = 3, Cols = 4 };
    int matrix[Rows][Cols];
    int ( & operator []( size_t i ) )[Cols]
    {
        return matrix[i];
    }
};

int main()
{
    A a;

    for ( size_t i = 0; i < a.Rows; i++ )
    {
        for ( size_t j = 0; j < a.Cols; j++ ) a[i][j] = a.Cols * i + j;
    }


    for ( size_t i = 0; i < a.Rows; i++ )
    {
        for ( size_t j = 0; j < a.Cols; j++ ) std::cout << std::setw( 2 ) << a[i][j] << ' ';
        std::cout << std::endl;
    }
}

The program output is

 0  1  2  3 
 4  5  6  7 
 8  9 10 11 

I have no idea how to build the operator [][] .

Sometimes it is fine to use a different operator, namely () :

int& Matrix::operator () (int x, int y)
{
    return matrix[x][y];
}

const int& Matrix::operator () (int x, int y) const
{
    return matrix[x][y];
}

int diagonal (const Matrix& m, int x)
{
    return m (x, x); // Usage.
}

Advantage :

  • No need to use "intermediate" class like Row or Column .

  • Better control than with Row& Matrix operator (int); where someone could use the Row reference to drop in a row of, say, illegal length. If Matrix should represent a rectangular thing (image, matrix in Algebra) that's a potential source of error.

  • Might be less tedious in higher dimensions, because operator[] needs classes for all lower dimensions.

Disadvantage:

  • Uncommon, different syntax.

  • No more easy replacement of complete rows / columns, if that's desired. However, replacing columns is not easy, anyway, provided you used rows to model (and vice versa).

In either case, there are pros and cons if the number of dimensions are not known at runtime.

I have a 2D array and I want to define a function that returns the value of the index that the user gives me using operator overloading. In other words:

void MyMatrix::ReturnValue()
{
    int row = 0, col = 0;
    cout << "Return Value From the last Matrix" << endl;
    cout << "----------------------------------" << endl;
    cout << "Please Enter the index: [" << row << "][" << col << "] =" << ((*this).matrix)[row][col] << endl;
}

The operation ((*this).matrix)[row][col] should return an int . I have no idea how to build the operator [][] .
Alternatively, I could concatenate a couple of calls to the operator [] , but I didn't succeed in it, because the first call to that operaror will return int* and the second one will return int , and it compel to build another operator, and I dont want to do that.

The data matrix is defined like

int** matrix; matrix = new int*[row];
if (matrix == NULL)
{
    cout << "Allocation memory - Failed";
}
for (int i = 0; i < row; i++)//Allocation memory
{
    matrix[i] = new int[col];
    if (matrix[i] == NULL)
    {
        cout << "Allocation memory - Failed";
        return;
    }
}

What can I do? Thank you,

I was looking for self-tested array replacement... Improved version returns reference or NULL reference and checks boundaries inside.

#include <iostream>
#include <iomanip>

template<typename T, int cols>
class Arr1
{
public:
    Arr1(T (&place)[cols]) : me(place) {};
    const size_t &Cols = cols;
    T &operator [](size_t i)
    {
        if (i < cols && this != NULL) return me[i];
        else {
            printf("Out of bounds !\n");
            T *crash = NULL;
            return *crash;
        }
    }
private:
    T (&me)[cols];
};
template<typename T, int rows, int cols>
class Arr2
{
public:
    const size_t &Rows = rows;
    const size_t &Cols = cols;
    Arr2() {
        ret = NULL;
        for (size_t i = 0; i < rows; i++) // demo - fill member array
        {
            for (size_t j = 0; j < cols; j++) matrix[i][j] = cols * i + j;
        }
    }
    ~Arr2() {
        if (ret) delete ret;
    }
    Arr1<T, cols>(&operator [](size_t i))
    {
        if (ret != NULL) delete ret;
        if (i < rows) {
            ret = new Arr1<T, cols>(matrix[i]);
            return *ret;
        }
        else {
            ret = NULL;
            printf("Out of bounds !\n");
            return *ret;
        }
    }
    //T(&MemberCheck)[rows][cols] = matrix;
private:
    T matrix[rows][cols];
    Arr1<T, cols> *ret;
};
template<typename T,int rows, int cols>
class Arr
{
public:
    const size_t &Rows = rows;
    const size_t &Cols = cols;
    T(&operator [](size_t i))[cols]
    {
        if (i < rows) return matrix[i];
        else {
            printf("Out of bounds !\n");
            T(*crash)[cols] = NULL;
            return *crash;
        }
    }
    T (&MemberCheck)[rows][cols] = matrix;
private:
    T matrix[rows][cols];
};

void main2()
{
    std::cout << "Single object version:" << endl;
    Arr<int, 3, 4> a;

    for (size_t i = 0; i <= a.Rows; i++)
    {
        int *x = &a[i][0];
        if (!x) printf("Fill loop - %i out of bounds...\n", i);
        else for (size_t j = 0; j < a.Cols; j++) a[i][j] = a.Cols * i + j;
    }

    for (size_t i = 0; i < a.Rows; i++)
    {
        for (size_t j = 0; j <= a.Cols; j++) {
            std::cout << std::setw(2) << a[i][j] << ' ';
            if (a.MemberCheck[i][j] != a[i][j])
                printf("Internal error !");
        }
        std::cout << std::endl;
    }

    std::cout << endl << "Double object version:" << endl;

    Arr2<int, 3, 4> a2;
    for (size_t i = 0; i < a2.Rows; i++)
    {
        for (size_t j = 0; j <= a2.Cols; j++) {
            int &x = a2[i][j];
            if (&x)
            {
                x++;
                std::cout << std::setw(2) << a2[i][j] << ' ';
                //if (&a2.MemberCheck[i][j] != &a2[i][j])
                //  printf("Internal error !");
            }
        }
    }
}

Output

Single object version:
Out of bounds !
Fill loop - 3 out of bounds...
 0  1  2  3  4
 4  5  6  7  8
 8  9 10 11 -858993460

Double object version:
 1  2  3  4 Out of bounds !
 5  6  7  8 Out of bounds !
 9 10 11 12 Out of bounds !

it works fine in the program below

#include<iostream>
using namespace std;
class A{
    public:
    int r,c;
    int** val;
    A()
    {
        r=0;c=0;val=NULL;
    }
    A(int row,int col)
    {
        r=row;c=col;
        int count=0;
        val=new int*[row];
        for(int i=0;i<r;i++){
            val[i]=new int[col];
            for(int j=0;j<c;j++){
                count++;
                val[i][j]=count;
            }
        }
    }
    int* &operator[](int index){
        return val[index];
    }
};
int main(void){
    A a(3,3);
    cout<<a[1][2];
    return 0;
}

here, a[1][2] first computes a[1]-->which returns 2nd row as (int*) type then it's read as (int*)[2] which returns 3rd element of that row.In short,

a[1][2]------>(a[1])[2]------>(val[1])[2]------>val[1][2].

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM