开发者

Const operator overloading problems in C++

I'm having trouble with overloading operator() with a const version:

#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 << "开发者_StackOverflow中文版 - 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; }
}

This gives me the following output:

  • NONconst-version was called - - NONconst-version was called - A(1,1)=8.8
  • NONconst-version was called - Error: you may only alter the first row of the matrix.

How can I achieve that C++ call the const-version of operator()? I am using GCC 4.4.0.


The overloading looks fine but you never call it on a const object. You can try this:

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

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

This gives you:

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


The object you are calling the method on must be const, e.g.

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


Generally, you can't call a const or non-const version of a function depending on what you do with the return value. If you want to emulate similar functionality, you can try returning some proxy that will switch the behaviour depending on what you do with it:

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

Assuming check() is your check for legal mutation (could be integrated in index()) and index() and const_index() are methods in Matrix that give a reference or const reference to a particular place.


Use const_cast<>() or make your instance const.

I'm guessing maybe you want to be sure the operator returns a const double? Maybe you should just provide the const version, not the other one.


You have different methods with different functionality, so give them different names. Then you don't need to have a const object just to call what you want.

You can still make operator() const call the alternative function in case you do happen have a const object. But the alternative functionality should be put in a function with a descriptive name.

As for getting a const handle to an object, use static_cast< const Matrix & >( A ).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜