C++ 错误:从';常数int*';至';int*';

C++ 错误:从';常数int*';至';int*';,c++,gcc,C++,Gcc,我想创建一个简单的3x3矩阵类,并能够通过下标操作符访问其内容。代码如下: // 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];

我想创建一个简单的3x3矩阵类,并能够通过下标操作符访问其内容。代码如下:

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

我希望能够访问数组的元素,无论矩阵的对象是常量还是非常量。但我从编译器中得到以下错误:

错误:从“常量int*”到“int*”的转换无效[-fpermissive]

我做了一些研究,我有一个假设:也许,因为我已经声明这个成员函数为常量函数,所以在它的定义中,编译器将对象的所有不可变成员都视为常量成员(它屏蔽),所以这就是为什么编译器说它是从“const int*”到“int*”的无效转换我的问题:这个假设正确吗?如果不是,为什么会发生这种情况?我认为这是有意义的,并且是确保“const Matrix*this”对象的常量的好方法

编译器信息:gcc 5.3.0从equation.com下载

int* Matrix::operator[](const int index) const {
    return this->matrix[index]; }
这里您可以说,您不需要通过将函数指定为
const
来修改对象的状态

但是您正在返回一个指向实例变量的指针——通过该指针可以更改类的实例变量的值(以及状态)


因此,您可以创建该运算符的非常量版本以避免该问题。

当您声明类方法(并且运算符是类方法)
const
时,这意味着您只能在类的字段上调用
const
方法,并且只能返回类字段的
const
指针或引用。为了进行编译,您需要下定决心:

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


或者两者都有。

关于出现错误的原因,您完全正确:在标记为
const
的成员函数中,编译器隐式处理类的所有数据成员,就好像它们是用
const
限定符声明的一样

修复非常简单-您可以覆盖同一个操作符两次,提供
const
和非
const
版本:

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

编译器将根据上下文确定要调用的重载。如果
矩阵
本身是
常量
,它将调用
常量
版本,而非
常量
版本则会调用
常量
版本。

由于从
常量成员函数
(或
运算符
)返回
指针,因此出现此错误

常量成员函数
运算符
不应更改任何
不可变
成员,也不应返回以后可以更改的
指针

使运算符返回常量指针而不是指针

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];
}
更改此选项:

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

const int* Matrix::operator[](const int index) const
不能从const函数返回指向数据成员的可变指针

或者,您可以创建两个版本的运算符:常量和非常量:

const int* Matrix::operator[](const int index) const;
int* Matrix::operator[](const int index);
另外,返回指向内部类成员的指针或引用是一种非常糟糕的做法。

希望这有助于:

#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;
}
#包括
使用名称空间std;
类矩阵
{
私人:
整数矩阵[3][3];
公众:
常量int*运算符[](常量int索引)常量;
矩阵(int*value);//需要一个初始值设定项:)
};
常量int*矩阵::运算符[](常量int索引)常量
{
返回此->矩阵[索引];
}
矩阵::矩阵(int*值)
{

对于(int i=0;我不知道常量函数中的返回限制,谢谢!但我希望得到有关编译器行为的一些答案。正如dasblinkenlight所说,我可以同时使用这两个函数!=我希望能够像访问二维数组一样访问矩阵成员(例如:矩阵m;m[2][1]=7.5;)还可以使用运算符重载执行其他矩阵操作(例如:矩阵m1,m2;m1+=m2;m2*=m1)。这就是我使用类的原因,“int matrix[3][3]”成员是私有的原因,只是为了隐藏实现。我想没有其他方法可以使用像m[2][1](下标运算符两次)这样的对象不返回指针,实际上我认为这样做没有问题。=)
#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;
}