C ++:非const运算符优先于const重载

时间:2014-04-23 03:31:16

标签: c++ const overloading

我有一个代表对角矩阵的类。我只沿着对角线存放元素,所以我不会浪费一大堆0的空间。但是,我仍然希望能够使用双括号来访问数组中的元素。为了解决这个问题,我使用了一个内部类,如下所示:

template <class T>
class DiagonalMatrix
{
private:
  const T ZERO = 0;

  int _size;
  Vector<T> _data;

  class row
  {
  private:
    DiagonalMatrix<T>* _parent;
    int _row;
  public:
    row(DiagonalMatrix<T>* parent, const int row)
      : _parent(parent), _row(row) {}
    T& operator[](const int i);
  };

  class const_row
  {
  private:
    const DiagonalMatrix<T>* const _parent;
    int _row;
  public:
    const_row(const DiagonalMatrix<T>* const parent, const int row)
      : _parent(parent), _row(row) {}
    const T& operator[](const int i) const;
  };
  friend class row;
  friend class const_row;

public:
  row             operator[] (const int i);
  const const_row operator[] (const int i) const;

  // other stuff
};

以下是相关定义:

template<class T>
typename DiagonalMatrix<T>::row DiagonalMatrix<T>::operator[](const int i)
{
  if (i < 0 || i >= _size)
  {
    throw IndexOutOfBoundsException(i);
  }
  return DiagonalMatrix<T>::row(this, i);
}

template <class T>
T& DiagonalMatrix<T>::row::operator[](const int i)
{
  if (i < 0 || i >= _parent->_size)
  {
    throw IndexOutOfBoundsException(i);
  }
  if (row == col)
  {
    return _parent->_data[row];
  }
  // TODO Add a real exception
  throw "Cannot modify non-diagonal elements";
}

对于const版本的类似定义,除了const运算符[]之外,返回对常量ZERO的引用,而不是为非对角元素抛出。

所以这就是我的问题:即使我不需要修改任何内容,也会调用非const版本。例如,这会抛出我的错误字符串:

DiagonalMatrix<double> diag(5);
// fill in the diagonal elements with some values
cout << diag[0][2] << endl;

但是,如果我删除运算符的非const版本,它的行为与预期一致并输出0 我也尝试过这样的事情:

      T& at(const int row, const int col);
const T& at(const int row, const int col) const;

// in main:
cout << diag.at(0, 2) << endl;

但这有同样的问题。所以我有两个问题:

1)为什么C ++在const版本中选择非const版本的函数,即使我没有分配给结果?不是运营商&lt;&lt;通常通过const&amp;
传递右手对象 2)我怎样才能解决这个问题?如果我可以帮助它,我宁愿没有单独的get()和set()函数。

1 个答案:

答案 0 :(得分:6)

  

1)为什么C ++在const版本中选择非const版本的函数,即使我没有分配给结果?不是运营商&lt;&lt;通常通过const&amp;?

传递右手对象

它选择非const版本,因为diag不是const对象。

  

2)我怎样才能解决这个问题?如果我可以帮助它,我宁愿没有单独的get()和set()函数。

您可以为diag定义一个const refrence并使用它来打印值:

const DiagonalMatrix<double> &const_diag = diag;
cout << diag[0][2] << endl; // call const version

或者您定义一个函数来打印值并传递一个const引用:

void show_diag(const DiagonalMatrix<double> &diag)
{
    cout << diag[0][2] << endl; // call const version
}

show_diag(diag);