2010-04-09 7 views
0

매트릭스 클래스를 작성 중이며 함수 호출 연산자를 두 번 오버로드했습니다. 행렬의 핵심은 2D 이중 배열입니다. Windows 콘솔에서 MinGW GCC 컴파일러를 사용하고 있습니다.operator() 오버로드가 잘못되었습니다.

첫 번째 오버로드는 요소를보기 위해 배열에서 double을 반환하기위한 것입니다. 두 번째 오버로드는 해당 위치에서 데이터를 변경 (배열의 위치에 대한 참조를 반환하기위한 것입니다.

double operator()(int row, int col) const ; //allows view of element 

double &operator()(int row, int col); //allows assignment of element 

내가 테스트 루틴을 쓰고 있어요하고 "보기"과부하라는 결코 극복 것을 발견했다 . 어떤 이유로 다음의 printf() 문을 사용하는 참조를 반환 과부하를 호출하는 컴파일러 "기본값".

fprintf(outp, "%6.2f\t", testMatD(i,j)); 

은 내가없이 내 자신의 매트릭스 클래스를 작성하여 신들을 모욕하고있어 이해 벡터를 사용하고 CI/O 기능으로 테스트하기. 나는 내세에서 철저히 처벌되며, 필요는 없습니다. 그것 여기.

궁극적으로 나는 여기에서 무슨 일이 일어나고 있고 그것을 고치는 지 알고 싶습니다. 나는 멤버 함수보다는 클리너를 찾는 연산자 오버로드를 선호한다.

아이디어가 있으십니까?

매트릭스 클래스 : 관련없는 코드가 생략되었습니다.


    class Matrix 

    { 
    public: 
double getElement(int row, int col)const; //returns the element at row,col 

//operator overloads 
double operator()(int row, int col) const ; //allows view of element 
double &operator()(int row, int col); //allows assignment of element 

    private: 
//data members 
double **array; //pointer to data array 

    }; 

    double Matrix::getElement(int row, int col)const{ 
    //transform indices into true coordinates (from sorted coordinates 
    //only row needs to be transformed (user can only sort by row) 
    row = sortedArray[row]; 

    result = array[usrZeroRow+row][usrZeroCol+col]; 
    return result; 
    } 

    //operator overloads 
    double Matrix::operator()(int row, int col) const { 
    //this overload is used when viewing an element 
    return getElement(row,col); 
    } 

    double &Matrix::operator()(int row, int col){ 
    //this overload is used when placing an element 
    return array[row+usrZeroRow][col+usrZeroCol]; 
    } 

테스트 프로그램 : 관련없는 코드가 생략되었습니다. 개체 CONST 경우

int main(void){ 

FILE *outp; 

outp = fopen("test_output.txt", "w+"); 

    Matrix testMatD(5,7); //construct 5x7 matrix 

    //some initializations omitted 
    fprintf(outp, "%6.2f\t", testMatD(i,j)); //calls the wrong overload 
} 
+4

이 프로그램이 C++ 인 경우 프로그램처럼 실행해야합니다. 'std :: vector', * not * 수동 메모리 관리를 사용하십시오. 'fopen' /'fclose' 대신에'fstream'을 사용하십시오 (힌트 : 후자가 빠짐). 또한'get' 함수를 사용하는 것이 이상하고, 하나의 과부하에 사용하고, 두 번째 과부하 (아무것도 읽지 않으면 행동 변경)와 아무런 관계가 없습니다. – GManNickG

답변

5

const 멤버 기능 ("보기"기능) 만 호출 될 것이다

const Matrix testMatD(5,7); 

testMatD(1, 2); // will call the const member function 
3

this를 포함하는 파라미터 (의해서만 결정된다라고 과부하 매개 변수)를 반환하고 리턴 유형이나 리턴 유형으로하지 마십시오.

즉 당신은 const 객체 호출 할 때 또는 그 const 방법 만 사용된다 (아마도 반환 형식 이격)을 const 방법과 달리 동일한 서명을 가진 비 const 방법이 있다면 참조 또는 포인터를 통해 const. 비 const 개체를 사용하면 비 const 메서드가 항상 더 잘 일치합니다.

일반적으로 반환 된 개체에 실제로 쓸지 여부를 구분할 수있는 유일한 방법은 읽기에 적합한 암시 적 변환과 쓰기위한 오버로드 된 할당 연산자가있는 일종의 프록시 개체를 반환하는 것입니다. 말할 필요도없이 이것은 대개 상당한 복잡성을 추가합니다.

0

다른 사람들이 언급했듯이 const 과부하의 전화를 받으려면 const 개체가 필요합니다.

여기에서 수행하려는 작업은 참조가 ...의 rvalue로 변환되었는지 확인하는 것입니다.

fprintf(outp, "%6.2f\t", double(testMatD(i,j))); // double() for temporary 

그러나, 변환은 자동적으로 수행 (§5.2.2/7) 따라서 특별한 고려가 필요하다.

또한 두 개의 오버로드가 일치하도록 선언 할 수도 있습니다. "뷰어"가 참조를 반환하도록하십시오.

double const &operator()(int row, int col) const ; //allows view of element 
1

안녕하십니까? 귀하의 도움에 감사드립니다. 유사한 질문에 대한 비슷한 답변을 읽었습니다. 나는 방금 조금 더 다르게 말한 것을 한 번 더 들어야한다고 생각한다.

내 원래의 문제는 두 가지 버전의 연산자 오버로드가 필요했기 때문에 연산자가 호출되는 방식에 따라 다르게 구현되었습니다.

- 사용자가 단순히 값을 읽어야 할 때 오버로드는 행렬을 const로 처리하고 사용자가 존재하지 않는 데이터를 읽지 않으려 고하는 경계를 검사합니다. - 사용자가 데이터를 써야 할 때 오버로드로 인해 매트릭스 크기가 조정됩니다.

물론 이것은 호출되는 메소드가 호출하는 메소드 나 사용자가 시도하려는 메소드에 대한 지식이 없기 때문에 (어떤 데이터가 전달되지 않는 한) 의미가 없습니다.

내 솔루션은 연산자 오버로드가 읽기 및 쓰기 모두에 대해 동일하게 실행되도록하는 것이 었습니다. 따라서 사용자가 존재하지 않는 위치를 읽으려고하면 행렬의 크기가 다시 지정되고 기본값이 반환됩니다. 궁극적으로 이것은 사용자가 실수를하고 존재하지 않는 데이터를 읽는 경우 약간의 속도를 희생시킬 수 있지만 사용자가 그렇게한다면 프로그램의 속도는 걱정거리가되지 않습니다. 그래서 이것은 사용자가 좀 더 조심해야하고, 데이터 멤버를 추가 할 수 있습니다.이 멤버는 행렬의 크기를 조정하여 사용자가 예상대로 작동하는지 쉽게 확인할 수 있는지 여부를 나타내는 플래그입니다.

더 높은 수준의/기능적인 문제 였기 때문에 코드를 게시하지 않을 것이고 (코드에는 토론을 흐리게 할 정도로 많은 세부 사항이 포함되어 있습니다.)