IT story

ostream에 << 연산자를 올바르게 오버로드하는 방법은 무엇입니까?

hot-time 2020. 4. 21. 08:22
반응형

ostream에 << 연산자를 올바르게 오버로드하는 방법은 무엇입니까?


행렬 작업을 위해 C ++로 작은 행렬 라이브러리를 작성하고 있습니다. 그러나 내 컴파일러는 전에는 그렇지 않은 곳에서 불평합니다. 이 코드는 6 개월 동안 선반에 있었고 컴퓨터를 데비안 에칭에서 레니 (g ++ (Debian 4.3.2-1.1) 4.3.2)로 업그레이드했지만 동일한 g ++의 우분투 시스템에서 동일한 문제가 있습니다. .

내 매트릭스 클래스의 관련 부분은 다음과 같습니다.

namespace Math
{
    class Matrix
    {
    public:

        [...]

        friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix);
    }
}

그리고 "구현":

using namespace Math;

std::ostream& Matrix::operator <<(std::ostream& stream, const Matrix& matrix) {

    [...]

}

이것은 컴파일러가 제공 한 오류입니다.

matrix.cpp : 459 : 오류 : 'std :: ostream & Math :: Matrix :: operator << (std :: ostream &, const Math :: Matrix &)'는 정확히 하나의 인수를 가져야합니다.

이 오류로 인해 약간 혼란 스럽지만 6 개월 동안 많은 Java를 수행 한 후에 C ++이 약간 녹슬 었습니다. :-)


함수를로 선언했습니다 friend. 수업의 회원이 아닙니다. Matrix::구현에서 제거해야합니다 . friend지정된 함수 (클래스의 멤버가 아님)가 개인 멤버 변수에 액세스 할 수 있음을 의미합니다. 함수를 구현 한 방식 Matrix은 잘못된 클래스 의 인스턴스 메소드와 같습니다 .


다른 가능성에 대해 이야기하는 것만으로도 친구 정의를 사용하는 것이 좋습니다.

namespace Math
{
    class Matrix
    {
    public:

        [...]

        friend std::ostream& operator<< (std::ostream& stream, const Matrix& matrix) {
            [...]
        }
    };
}

함수는 해당 네임 스페이스 Math의 범위 내에 정의가 표시 되더라도 주변 네임 스페이스를 자동으로 대상으로 지정 하지만 인수 종속 조회로 해당 연산자 정의를 찾도록하는 Matrix 객체로 operator <<를 호출하지 않으면 표시되지 않습니다. 모호한 호출에 도움이 될 수 있습니다. Matrix 이외의 인수 유형에서는 보이지 않기 때문입니다. 정의를 작성할 때 긴 접두사로 이름을 한정하고와 같은 템플릿 매개 변수를 제공하지 않고도 Matrix에 정의 된 이름과 Matrix 자체를 직접 참조 할 수도 있습니다 Math::Matrix<TypeA, N>.


Mehrdad answer에 추가하려면

namespace Math
{
    class Matrix
    {
       public:

       [...]


    }   
    std::ostream& operator<< (std::ostream& stream, const Math::Matrix& matrix);
}

당신의 구현에서

std::ostream& operator<<(std::ostream& stream, 
                     const Math::Matrix& matrix) {
    matrix.print(stream); //assuming you define print for matrix 
    return stream;
 }

우리가 과부하에 대해 얘기하고 있다고 가정 operator <<에서 파생 된 모든 클래스에 대한 std::ostream핸들을 Matrix(오버로드가 아닌 클래스 <<에 대한 Matrix클래스), 그것은 헤더의 수학 네임 스페이스 외부에 과부하 함수를 선언 더 의미가 있습니다.

공용 인터페이스를 통해 기능을 수행 할 수없는 경우에만 친구 기능을 사용하십시오.

Matrix.h

namespace Math { 
    class Matrix { 
        //...
    };  
}
std::ostream& operator<<(std::ostream&, const Math::Matrix&);

연산자 오버로드는 네임 스페이스 외부에서 선언됩니다.

Matrix.cpp

using namespace Math;
using namespace std;

ostream& operator<< (ostream& os, const Matrix& obj) {
    os << obj.getXYZ() << obj.getABC() << '\n';
    return os;
}

반면에, 당신의 과부하 기능은 경우 않습니다 즉 개인 보호 멤버에 대한 액세스를 필요로하는 친구를 할 필요가있다.

Math.h

namespace Math {
    class Matrix {
        public:
            friend std::ostream& operator<<(std::ostream&, const Matrix&);
    };
}

함수 정의를 just 대신 네임 스페이스 블록으로 묶어야합니다 using namespace Math;.

Matrix.cpp

using namespace Math;
using namespace std;

namespace Math {
    ostream& operator<<(ostream& os, const Matrix& obj) {
        os << obj.XYZ << obj.ABC << '\n';
        return os;
    }                 
}

C ++ 14에서는 다음 템플릿을 사용하여 T :: print (std :: ostream &) const; 회원.

template<class T>
auto operator<<(std::ostream& os, const T& t) -> decltype(t.print(os), os) 
{ 
    t.print(os); 
    return os; 
} 

참고 URL : https://stackoverflow.com/questions/476272/how-to-properly-overload-the-operator-for-an-ostream

반응형