2017-10-28 11 views
2

<< 연산자 오버로드의 반환 유형이 std::string 인 경우 컴파일러가 오류를 고발하는 이유를 이해하는 데 문제가 있습니다. 이해하는데 도와 주실 수 있겠습니까?<< 연산자 오버로드로 인해 std :: string을 반환하는 중 오류가 발생했습니다

벨로우 (Bellow)는 재현 가능한 예이며, 이는 거대한 오류를 나타냅니다.

class XY 
{ 
    int X__; 
    int Y__; 
public: 
    XY(int x, int y):X__(x), Y__(y){} 
    ~XY(){} 

    std::string operator<<(const XY_cartesiano& c) 
    { 
     std::stringstream ss; 
     ss << "{ " << X__ << ", " << Y__ << " }"; 
     return ss.str(); 
    } 

    int x() const{return X__;} 
    int y() const{return Y__;} 
}; 

void main() 
{ 

XY a(1,2); 
std::cout << a; 
} 
+1

를이 문제가 아니라 대문자 다음에 밑줄로 시작하는 두 개의 연속 밑줄 ('X__','Y__') 및 이름을 포함하는 이름 구현에서 사용하도록 예약되어 있습니다. 코드에서 사용하지 마십시오. –

답변

3

의 예로 들어 같은 것을 보자,

cout << "My number is " << 137 << " and I like it a lot." << endl; 

이 특히

((((cout << "My number is ") << 137) << " and I like it a lot.") << endl); 

로 분석됩니다 발현 cout << "My number is " 뭔가로 평가하는 것을 알 때 너무 << 137과 함께 137을 삽입 해보십시오. 의미는 "137을 가져와 cout으로 보내주십시오."

cout << "My number is "string을 반환하는 경우를 상상해보십시오. 이 경우 << 137 비트는 string 왼쪽과 오른쪽에서 int 사이의 << 연산자를 사용하려고 시도합니다.이 연산자는 C++에서 잘 정의되지 않았습니다.

전통적으로 스트림 삽입 연산자 operator <<은 왼쪽 스트림이 무엇이든간에 이러한 연산이 잘 연결되도록 참조를 반환합니다. 그런 식으로 << 137의 왼쪽에있는 것은 결국 cout이되어 결국 위의 코드는 결국 cout에 물건을 삽입하는 일련의 연결 호출이됩니다. 따라서 이러한 함수의 서명은 보통 다음과 같습니다.

ostream& operator<< (ostream& out, const ObjectType& myObject) { 
    // ... do something to insert myObject into out ... // 
    return out; 
} 

이제 모든 것이 제대로 연결됩니다. 이 함수는 멤버 함수가 아닌 자유 함수이며, 왼쪽은 ostream이고 오른쪽은 클래스의 유형입니다. operator <<을 멤버 함수로 오버로드하려고하면 왼쪽은 클래스 삽입 유형의 피연산자가 될 것이므로 스트림 삽입이 작동하는 방식에서 거꾸로됩니다. 귀하의 경우 << 연산자를 오버로드

class XY { 
public: 
     ... 
     friend ostream& operator<< (ostream& out, const XY& myXY); 
}; 

ostream& operator<< (ostream& out, const XY &myXY) { 
    ... 
    return out; 
} 
1

올바른 방법으로 당신은이

ostream& operator<<(ostream& os, const XY& c) 
{ 
    os << c.X__ <<" "<< c.Y__ ; 
    return os; 
} 
+0

'os'가 너비 수정 자 세트 (또는 다른 일시적인 스트림 수정 자)를 가지고있는 경우에 한 번에 출력되는 전체 문자열을 생성하기 위해 내부적으로'ostringstream'을 사용하여 출력이 부분적으로 엉망이되지 않게하는 것이 가장 좋습니다. – templatetypedef

1

됩니다 : 특별히이 기능을 구현하는 과정에서 클래스의 private 필드에 액세스해야하는 경우, 그것을 친구를 만들 std::ostream 개체 (예 : std::cout)를 사용할 때 따라야하는 규칙과 호환되지 않는 방식으로 operator<<이 오버로드되었습니다.

사실, operator<<의 서명은 스트림과 전혀 관련이 없습니다! XY의 멤버 함수이며 다른 XY (사용하지 않음)을 반환하고 문자열을 반환하며 비 정규 이름을가집니다.,

XY a(1,2); 
XY b(1,2); 
std::string x = (a << b); 

스트림을 사용 operator<<를 오버로드하는 올바른 방법은 운영자가 아닌 멤버 함수를 만드는 것입니다 스트림 참조 매개 변수를 추가하고 스트림 인수 스트림 참조를 반환 : 다음은 이론적으로 호출 할 방법 . 또한 문자열 스트림이 필요하지 않습니다. 당신이 스트림에 직접 쓰기 당신이 얻을 :

#include <iostream> 

class XY 
{ 
    int x; 
    int y; 
public: 
    XY(int x, int y) : x(x), y(y) {} 

    int X() const { return x; } 
    int Y() const { return y; } 
}; 

std::ostream& operator<<(std::ostream& os, XY const& c) 
{ 
    os << "{ " << c.X() << ", " << c.Y() << " }"; 
    return os; 
} 

int main() 
{ 
    XY a(1,2); 
    std::cout << a; 
}