Reputation: 143
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,
Upvotes: 12
Views: 17784
Reputation: 16706
As of C++23, the subscript operator is now multidimensional. Simply define your overloads for the required number of dimensions:
my_type &operator[](size_t x) { // one-dimenisonal
// return ...
}
my_type &operator[](size_t x, size_t y) { // two-dimensional
// return ...
}
my_type &operator[](size_t x, size_t y, size_t z) { // three-dimensional
// return ...
}
// etc
Upvotes: 0
Reputation: 11
There is no need to overload [][]
in C++. In C and C++, a subscript ([]
) is just an clearer way of referencing an array element. Since arrays are just pointers, for int myArray[4]
, myArray[2] == *(myArray + 2)
. Therefore, overloading just []
is sufficient.
#include <iostream>
class Matrix {
public:
enum Dims { Rows = 3, Cols = 3 };
Matrix() {
for (int i = 0; i < Rows; i++) {
for (int j = 0; j < Cols; j++) {
m[i][j] = (i + 1) * 10 + (j + 1);
}
}
}
void print() {
for (int i = 0; i < Rows; i++) {
for (int j = 0; j < Cols; j++) {
std::cout << '@' << i << ',' << j << ": " << m[i][j] << " ";
}
std::cout << std::endl;
}
}
int *operator[](int x) { return m[x]; }
private:
int m[Rows][Cols];
};
int main() {
Matrix m;
m.print();
std::cout << std::endl << "setting m[1][2] = 99\n";
m[1][2] = 99;
std::cout << "@1,2: " << m[1][2] << std::endl << std::endl;
m.print();
return EXIT_SUCCESS;
}
Upvotes: 0
Reputation: 1
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].
Upvotes: -1
Reputation: 2249
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 !
Upvotes: 0
Reputation: 3918
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.
Upvotes: 4
Reputation: 50550
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.
Upvotes: 14
Reputation: 311038
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
Upvotes: 9