两个方括号的重载

14

我正在用C++编写矩阵类,尝试重载一些运算符,比如=、>>和<<等。

我无法为矩阵类重载运算符[][]。 如果我有一个名为M1的矩阵类对象,我可以使用以下方式为每个元素赋值:

M1[1][2]=5;

或者

int X;

X=M1[4][5];

请访问以下链接:https://dev59.com/uEvSa4cB1Zd3GeqPhdGO#2216055 - Jerry Coffin
8个回答

23

只需重载operator[]并使其返回矩阵的相应行或列的指针。由于指针支持使用[]下标符进行索引,因此可以使用“双方括号”符号[][]进行访问。

您还可以使用两个参数重载operator()


1
我更喜欢RedX的解决方案,因为在我看来,除非你绝对必须使用指针,否则不应该在C++中使用它们。 - Björn Pollex
13
在这种情况下,我发现 operator(x,y) 是一个不错的解决方案。 - edA-qa mort-ora-y
1
你如何使用两个参数重载operator()?当我尝试这样做时,编译器会报错,指出它“必须只接受一个参数”。 - Charlie Su

12

在 C++ 中没有 operator[][] 运算符。您需要返回一个辅助对象,然后再为其重载 operator[] 来实现这种访问方式。


9
您可以重载operator[]。因此,如果您想以这种方式使用矩阵,则应将矩阵作为向量数组进行处理。
class Matrix
{
...
  Vector & operator[]( int index );
...
};

并且

class Vector
{
...
  double & operator[]( int index );
...
};

最后:

Matrix m;
...
double value = m[i][j];
...

5

在C++中没有operator[][],但你可以实现operator[]来返回一个引用到行/列对象,在这个对象中你可以实现operator[]来返回单元格的引用。

你可以像下面这样做来避免所有的麻烦..

struct loc
{
  int x;
  int y;
};

在您的operator[]重载中,接受一个loc,例如:

T& operator[](loc const& cLoc)
{
 // now you have x/y you can return the object there.
}

要进行调用,你可以简单地执行以下操作:
matrix[loc(2,3)] = 5; 

这是一个我以前没有见过的有趣想法,但它仍然很明显它的作用是什么。 - David Stone

3

事实上,几年前我在自己的矩阵类中就做到了这一点。在这种情况下,我定义了一个包含以下片段的矩阵模板类。

然后,我可以按如下方式进行迭代和赋值:

          for(size_t k=1; k<n; ++k) {       
                   minor[p][k-1]=major[j][k];        
           }

我希望这能帮到你。
// //////////////////////////////////////////////////////////////////////////////
// list is internal vector representation of n x m matrix
T* list;
// Proxy object used to provide the column operator
template < typename T >
class OperatorBracketHelper
{
    Matrix < T > & parent ;
    size_t firstIndex ;

    public :
        OperatorBracketHelper ( Matrix < T > & Parent , size_t FirstIndex ) : 
        parent ( Parent ), firstIndex ( FirstIndex ) {}

        // method called for column operator
        T & operator []( size_t SecondIndex )
        {
            // Call the parent GetElement method which will actually retrieve the element
            return parent.GetElement ( firstIndex , SecondIndex );
        }
};

// method called for row operator
OperatorBracketHelper < T > operator []( size_t FirstIndex )
{
    // Return a proxy object that "knows" to which container it has to ask the element
    // and which is the first index (specified in this call)
    return OperatorBracketHelper < T >(* this , FirstIndex );
}

T & GetElement ( size_t FirstIndex , size_t SecondIndex )
{
    return list[FirstIndex*cols+SecondIndex];
}

2
我正在编写一个矩阵类,决定先创建一个动态二维数组的Array类。所以,就像你一样,我遇到了如何重载两个方括号的难题。我采用的方法很简单:我将方括号运算符作为成员函数进行了两次重载。首先,我重载了[],以返回指向所需行的指针,然后是下一个成员函数(即再次重载的[]运算符),返回与数组元素相同类型的左值。
但是,请注意,您调用前面重载的[]运算符时输入的索引必须保存在某处,以便在后面重载的[]运算符中使用。因此,我只是在Array类中添加了一个新的int类型成员(在我的代码中命名为“test”)。
class Array {

private: 

 double **ptr; int test;
 ...   /* the rest of the members includes the number of rows and columns */

public:
    Array(int=3,int=3);  // Constructor
    Array(Array &);      // Copy Constructor
    ~Array();            // Destructor
    void get_array();
    void show_array();
    double* operator[] (int);
    double operator[] (short int);
    ...
};

... 

double* Array::operator[] (int a) {
    test = a;
    double* p = ptr[test];
    return p;
}

double Array::operator[] (short int b) {
   return ((*this)[test][b]);
}

因此,以一个例子来说明,在主函数中我可以简单地编写如下代码:
int main(){
Array example;
cout << example[1][2];  
}

我希望这能帮到你。

0

模板矩阵类

template <uint8_t rows, uint8_t cols, typename T>
class MatrixMxN {
public:
    T* operator[](uint8_t f_row) {
        return &m_val[f_row * cols];
    }
protected:
    T m_val[rows*cols];
};

这里是一个3行4列的整数类型矩阵对象。

MatrixMxN<3, 4, int32_t> M;
M[2][3] = 10;
std::cout << M[2][3] << std::endl;

0

你不能像这样重载[][],因为没有这样的运算符。你可以重载[],返回一个也定义了[]的东西(代理);在最简单的情况下,像double*这样的东西就可以工作,但通常更好,虽然需要更多的工作,使用一个完整的类。(例如添加边界检查的地方。)

或者,你可以重载(x,y)。根据你问的人,其中一种格式比另一种“更好”。(实际上,这严格是一个风格问题。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接