2010-05-28 6 views
1

여기 내가 쓴 작은 테스트 프로그램입니다 : 내가 선이 표시된 이유를 얻이 수없는 것왜 연산자 << 연산자에 의해 반환 된 뭔가 작동하지 않습니다?

#include <iostream> 
using namespace std; 

class A { 

    public: 
    int val; 

    A(int _val=0):val(_val) { } 

    A operator+(A &a) { return A(val + a.val); } 
    A operator-(A &a) { return A(val - a.val); } 

    friend ostream& operator<<(ostream &, A &); 

}; 

ostream& operator<<(ostream &out, A &a) { 
    out<<a.val; 
    return out; 
} 

int main() { 
    A a(3), b(4), c = b - a; 
    cout<<c<<endl; // this works 
    cout<<(b-a)<<endl; // this doesn't 
    return 0; 
} 

작품을 "이 작품"과 하나가 "이되지 않는다"하지 않습니다 표시했다. 나는 cout<<(b-a); 라인 프로그램을 컴파일 할 때, 여기에 내가 무엇을 얻을 : 아주 불쾌한

[[email protected] C]$ g++ test.cpp 

test.cpp: In function ‘int main()’: 
test.cpp:26:13: error: no match for ‘operator<<’ in ‘std::cout << b.A::operator-(((A&)(& a)))’ 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:108:7: note: candidates are: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:117:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ios_type& (*)(std::basic_ostream<_CharT, _Traits>::__ios_type&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>, std::basic_ostream<_CharT, _Traits>::__ios_type = std::basic_ios<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:127:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:165:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:169:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:173:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/ostream.tcc:91:5: note:     std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:180:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/ostream.tcc:105:5: note:     std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:191:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:200:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:204:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:209:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:213:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:221:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/ostream:225:7: note:     std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream<char>] 
/usr/lib/gcc/i686-pc-linux-gnu/4.5.0/../../../../include/c++/4.5.0/bits/ostream.tcc:119:5: note:     std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__streambuf_type*) [with _CharT = char, _Traits = std::char_traits<char>, std::basic_ostream<_CharT, _Traits>::__streambuf_type = std::basic_streambuf<char>] 
test.cpp:18:11: note:     std::ostream& operator<<(std::ostream&, A&) 
[[email protected] C]$ 

합니다.

답변

10

운영자가 + 임시 객체를 반환합니다. C++에서는 비 const 참조에 임시 객체를 바인딩 할 수 없습니다. 당신이 원하는 :

ostream& operator<<(ostream &out, const A &a) { 

이 정식 작성하는 방법 opertaor 스트리밍을위한 < <합니다 - 일이되는 출력은 항상 const를 참조로 전달해야한다.

+0

브릴리언트. 사실, 제 연구실 선생님은 그 사실을 알 수 없었습니다. – Felix

3

임시 연산자를 삽입 연산자에 전달할 수 없기 때문에. 그것을 다음으로 변경하십시오 :

friend ostream& operator<<(ostream &, const A &); 
... 
ostream& operator<<(ostream &out, const A &a) { 
    out<<a.val; 
    return out; 
} 
3

두 번째 줄에서 컴파일러에게 A에서 A로 변환 할 것을 요청하면 &이 임시이지만 A는 비표준 동작입니다. 첫 번째 줄에서 c는 일시적이지 않으므로 작동합니다.

ostream& operator<<(ostream &out, const A &a) 

에 운영자의 변경은 더 정확하지 않을뿐만 아니라 컴파일러에 의해 승인되어야한다.

1

operator<<에 임시 개체를 전달하므로 const A&이 필요합니다.

std::ostream& operator<<(std::ostream&, const A&) 

다른 몇 가지주의 사항 : 수정되지 않은 원시 인수를 전달할 때

항상 'const를 T &'를 사용합니다. 이렇게하면 임시 변수를 전달할 수 있으며 매개 변수를 변경하지 않았 음을 나타냅니다.

단일 인수 생성자 explicit을 표시하는 것이 가장 좋습니다. 이렇게하면 우발적 인 임시 개체를 도처에 만들지 않아도되므로 성능이 저하됩니다. 당신의 사용

ostream& operator<<(ostream &out, A const &a) // ... 
1

이 임시 객체가 기본적으로 const 간주됩니다, 그것은 const를 참조되어야한다 케이스. 따라서, 당신은 다음과 같이 운전자의 서명을 수정해야합니다 그런데

ostream& operator<<(ostream &out, A const& a) 

A::val 어쨌든 이렇게 접근, 공공 때문에 우정은 중복입니다.

+0

형식 뒤에 모든 한정자를 넣는 것을 선호하는 유일한 사람은 아닙니다. 그것은 어리석은 것처럼 보일지 모르지만 사람들이'const char &'로'T = char *'를 사용하여'const T &'를 해석하면 ...그들은 더 이상 어떤 일이 일어나는지 이해하지 못합니다./ –

+0

@Matthieu : 예, 대부분의 영어 사용자는 명사 앞에 형용사를 사용하지만 C와 C++의 동등한 기능은 잘 작동하지 않습니다. 나는 후위 수식어를 사용하기 때문에 프랑스어를 사용하는 사람들에게 더 자연 스럽다고 생각한다. –

+0

재미있는 것은 영어 코더가 트렌드를 설정했기 때문에 프랑스 코더도 그렇게합니다 :) –

0

std::basic_ostream::operator<< 예상하는 const를 수식 인수 : 참조가에 바인딩에 대한 있도록

explicit A(int _val=0):val(_val) { } 
관련 문제