Проблемы перегрузки операторов Const в C++

У меня проблемы с перегрузкой operator() с константной версией:

#include <iostream>
#include <vector>
using namespace std;

class Matrix {
public:
    Matrix(int m, int n) { 
        vector<double> tmp(m, 0.0);
        data.resize(n, tmp);
    }
    ~Matrix() { }


    const double & operator()(int ii, int jj) const {
        cout << " - const-version was called - ";
        return data[ii][jj];
    }

    double & operator()(int ii, int jj) {
        cout << " - NONconst-version was called - ";
        if (ii!=1) {
            throw "Error: you may only alter the first row of the matrix.";
        }
        return data[ii][jj];
     }


protected:  
    vector< vector<double> > data;
};

int main() {
try {
    Matrix A(10,10);
    A(1,1) = 8.8;
    cout << "A(1,1)=" << A(1,1) << endl;
    cout << "A(2,2)=" << A(2,2) << endl;
    double tmp = A(3,3);
} catch (const char* c) { cout << c << endl; }
}

Это дает мне следующий вывод:

  • NONconst-версия была названа - - NONconst-версия была названа - A(1,1)=8,8
  • Была названа NONconst-версия - Ошибка: вы можете изменять только первый ряд матрицы.

Как я могу добиться, чтобы C++ вызывал const-версию operator()? Я использую GCC 4.4.0.

5 ответов

Перегрузка выглядит нормально, но вы никогда не вызываете ее для объекта const. Вы можете попробовать это:

void foo(const Matrix& A) {
  cout << "A(1,1)=" << A(1,1) << endl;
}

Matrix A(10,10);
foo(A);

Это дает вам:

 - const-version was called - A(1,1)=0

Объект, для которого вы вызываете метод, должен быть постоянным, например

cout << "A(2,2)=" << (*static_cast<const Matrix*>(&A))(2,2) << endl;

Как правило, вы не можете вызвать постоянную или неконстантную версию функции в зависимости от того, что вы делаете с возвращаемым значением. Если вы хотите эмулировать аналогичную функциональность, вы можете попробовать вернуть прокси-сервер, который переключит поведение в зависимости от того, что вы с ним делаете:

class Proxy
{
  Matrix& m;
  int x, y;
public:
  ...
// mutating operations
  operator double&() { check(); return m.index(x,y); }
  double& operator=(double d) { check(); return m.index(x,y)=d; }
// ... other mutating operations (+=, ...) analogously

// nonmutating ops
  operator double() { return m.const_index(x, y); }
  operator const double&() // ... same
};

Proxy Matrix::operator(int x, int y)
{
  return Proxy(*this, x, y);
}

Если предположить, check() ваша проверка на легальную мутацию (может быть интегрирована в index()) а также index() а также const_index() Методы в матрице, которые дают ссылку или постоянную ссылку на конкретное место.

У вас есть разные методы с разной функциональностью, поэтому дайте им разные имена. Тогда вам не нужно иметь const возражать просто называть то, что вы хотите.

Вы все еще можете сделать operator() const Вызовите альтернативную функцию, если у вас есть объект const. Но альтернативная функциональность должна быть помещена в функцию с описательным именем.

Что касается получения const обращаться к объекту, использовать static_cast< const Matrix & >( A ),

Используйте const_cast<>() или сделайте ваш экземпляр const.

Наверное, вы хотите быть уверены, что оператор возвращает const double? Может быть, вы должны просто предоставить версию const, а не другую.

Другие вопросы по тегам