2010-03-14 4 views
3
나는 CONST 버전 (-) 연산자를 오버로딩에 문제가있어

:헌장 연산자

  • 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.

나는 것을 달성 할 수있는 방법 :

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

이 나에게 다음과 같은 출력을 제공합니다 C++은 operator()의 const 버전을 호출합니까? 나는 GCC 4.4.0을 사용하고있다.

+0

매트릭스 항목을 수정하고 수정할 수 있기를 원합니다. – steigers

답변

0

const_cast <>()을 사용하거나 인스턴스를 const로 만듭니다.

아마도 연산자가 const double을 반환하는지 확인하고 싶을 것입니다. 다른 버전이 아닌 const 버전 만 제공하면됩니다.

2

메소드를 호출 할 객체는 const 여야합니다.

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

흠, 그런 종류의 모순은 "그 사용법은 간단합니다"- 그 패러다임을 사용하고 싶었던 패러다임을 모순됩니다 ... – steigers

+5

음, 이것은 거의 절대 필요하지 않습니다. 당신의 const 버전과 non-const 버전은 동작이 매우 비슷해야합니다. 아마도 당신을 위해 컨테이너의 크기를 변경하지 않는 non-const 버전을 제외하고 가능할 것입니다. 두 버전에서 완전히 다른 것을 수행하는 경우, 다른 버전을 사용하는 것이 좋습니다. –

+0

행렬의 대각선 근처에있을 때만 non-const 연산자()를 호출 할 수있는 줄무늬 행렬을 원했습니다. 그렇지 않으면 요소가 저장되지 않고 암시 적으로 0이 아니므로 연산자에서 오류). 나는 지금 다른 방법을 할 것이다. – steigers

3

과부하가 잘 보이지만 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 
+0

고마워요! C++은 const가 아닌 객체에서도 "기본적으로"const-methods를 호출하지 않는다는 것이 제 생각에는 불행합니다. 나는 그것을 위시리스트에 넣을 것이다. – steigers

+1

그럴 경우 비 const 메소드는 언제 호출할까요? 당신은 항상 non-const 과부하를 제거 할 수 있으며, const가 아닌 객체에서도 const를 호출 할 것입니다. –

+0

비 const 연산을 수행해야 할 때 호출됩니다. 예, const가 아닌 오버로드 된 메서드를 제거 할 수 있지만 때로는 기능을 축소하는 행렬 요소에 무언가를 할당하려고합니다. 조언 해주셔서 감사합니다. – steigers

1

일반적으로, 당신은 당신이 반환 값과는 내용에 따라 함수의 const를 또는 const가 아닌 버전을 호출 할 수 없습니다. 법적 돌연변이 검사 (index()에 통합 될 수있다)이며

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()const_index()은 특정 장소에 대한 참조 또는 const 참조를 제공하는 Matrix의 메소드입니다.

+0

좋아요, 고급 ... 그것에 대해 생각할 것입니다 :-) – steigers

+0

사실,이 컴파일되지 않습니다 : operator double() {return m.const_index (x, y); } operator const double &() operator double() {return m.const_index (x, y);}이 연산자는 두 번째 줄의 끝에 const를 추가하는 반면 컴파일합니다. }; 연산자 const double &() const; – doizuc

0

다른 기능을 가진 다른 방법이 있으므로 다른 이름을 지정하십시오. 그러면 원하는 것을 호출하기 위해 const 개체를 가질 필요가 없습니다.

이 발생하면 operator() const이 대체 기능을 호출하도록 만들 수 있습니다.에는 const 개체가 있습니다. 그러나 대체 기능은 설명이 포함 된 이름을 가진 함수에 넣어야합니다.

const 개체를 처리하는 방법은 static_cast< const Matrix & >(A)을 사용하십시오.