4

I want to create a simple 3x3 matrix class and be able to access its contents by the subscript operator. Here's the code:

// Matrix.h
class Matrix {
private:
    int matrix[3][3];
public:
    int* operator[](const int index) const;
};

// Matrix.cpp
int* Matrix::operator[](const int index) const {
    return this->matrix[index];
}

I want to be able to access the elements of the array no matter whether the Matrix's object is const or non-const. But I get the following error from the compiler:

error: invalid conversion from 'const int*' to 'int*' [-fpermissive]

I did some research and I have a hypothesis: maybe, because I have declared this member function as a const function, inside its definition the compiler treats (it masks) all of the the object's non-mutable members as const members, so that would be the reason the compiler says it's an invalid conversion from 'const int*' to 'int*'. My question: Is this hypothesis correct? And if it's not, why does that happens? I think it makes sense and would be a great way of ensuring the const-ness of the 'const Matrix *this' object.

Compiler Info: gcc 5.3.0 downloaded from equation.com

null
  • 101
  • 2
  • 9

6 Answers6

4

You are absolutely right about the reason why you get the error: inside a member function marked const the compiler implicitly treats all data members of the class as if they were declared with a const qualifier.

The fix is really straightforward - you can override the same operator twice, providing a const and a non-const versions:

class Matrix {
private:
    int matrix[3][3];
public:
    const int* operator[](const int index) const;
    int* operator[](const int index);
};

// Matrix.cpp
const int* Matrix::operator[](const int index) const {
    return this->matrix[index];
}
int* Matrix::operator[](const int index) {
    return this->matrix[index];
}

The compiler will figure out which overload to call based on the context. It will call const version if the Matrix itself is const, and the non-const version otherwise.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
3

When you declare a class method (and operator is a class method) const, that means you can only call const methods on your class's fields and return only const pointers or references to class fields. In order to compile, you need to make up your mind to have either:

const int* Matrix::operator[](const int index) const { return this->matrix[index]; }

or

int* Matrix::operator[](const int index) { return this->matrix[index]; }

or both.

Jakub Zaverka
  • 8,816
  • 3
  • 32
  • 48
  • Didn't know about the return limitation in const functions, thanks! But I was expecting some answer about the compiler's behavior. And as dasblinkenlight said I can have both functions! =D – null Feb 12 '16 at 08:44
2
int* Matrix::operator[](const int index) const {
    return this->matrix[index]; }

Here you say you don't modify the state of your object by specifying function as const.

But you are returning a pointer to your instance variable - and through that pointer it is possible to change value of the instance variable of your class (and thus the state).

So you can create a non const version of that operator to avoid that issue.

Giorgi Moniava
  • 27,046
  • 9
  • 53
  • 90
0

You are getting this error because you are return a pointer from a const member function (or operator).

const member function and operator should not change any non-mutable member neither return pointers that can change them later.

Make your operator return const pointer rather than pointer.

class Matrix {
private:
    int matrix[3][3];
public:
    int const* operator[](const int index) const;
};

// Matrix.cpp
int const* Matrix::operator[](const int index) const {
    return this->matrix[index];
}

Live Demo

Humam Helfawi
  • 19,566
  • 15
  • 85
  • 160
0

Change this:

int* Matrix::operator[](const int index) const

to this

const int* Matrix::operator[](const int index) const

You cannot return mutable pointer to data member from const function.

Or you may create two versions of operator: const and non const:

const int* Matrix::operator[](const int index) const;
int* Matrix::operator[](const int index);

PS. And anyway it's a very bad practice to return pointer or reference to internal class members.

vladon
  • 8,158
  • 2
  • 47
  • 91
  • I want to be able to access the matrix member as if it was a 2-dimensional array (eg: Matrix m; m[2][1] = 7.5;) and also be able to do other matrix operations using operator overloading (eg: Matrix m1, m2; m1 += m2; m2 *= m1). So that's why I am using an class, and the reason why the 'int matrix[3][3]' member is private is just for hiding the implementation. I guess there's no other way of using the object like m[2][1] (subscript operator twice) without returning a pointer, and actually I see no problem in doing that. =) – null Feb 12 '16 at 09:06
0

hope this helps:

#include<iostream>
using namespace std;

class Matrix
{
private:
    int matrix[3][3];
public:
    const int* operator[](const int index) const;
    Matrix(int* value); // need an initializer though :)
};

const int* Matrix::operator[](const int index) const
{
    return this->matrix[index];
}

Matrix::Matrix(int* value)
{
    for(int i=0; i<3;i++)
    {
        for (int j=0; j<3; j++)
        {
            matrix[i][j]= *value;
            value++;
        }
    }
}

int main( void )
{
    int arr[] = {1,2,3,4,5,6,7,8,9};
    Matrix C(arr);

    const int *c;
    c = C[0];

    for(int i=0;i<3;i++)
    {
        cout << *c << ends;
        c++;
    }
    return 0;
}