Some old person at work is taking C++ and I was trying to help him out but have no experience on friend functions.
The attached program shows the friend operator overload works when the function is implemented after the prototype declaration only. Doing this otherwise, the program spits out errors that the friend function cannot support private member objects (supposedly it should, right?).
Compiling... TwoD.cpp c:\blah\twod.h(31) : error C2248: 'x' : cannot access private member declared in class 'TwoD' c:\blah\twod.h(8) : see declaration of 'x' c:\blah\twod.h(31) : error C2248: 'x' : cannot access private member declared in class 'TwoD' c:\blah\twod.h(8) : see declaration of 'x' c:\blah\twod.h(31) : error C2248: 'y' : cannot access private member declared in class 'TwoD' c:\blah\twod.h(8) : see declaration of 'y' c:\blah\twod.h(31) : error C2248: 'y' : cannot access private member declared in class 'TwoD' c:\blah\twod.h(8) : see declaration of 'y' C:\blah\TwoD.cpp(21) : error C2593: 'operator !=' is ambiguous Error executing cl.exe. TwoD.exe - 5 error(s), 0 warning(s)
class TwoD private: int x,y public: friend bool operator!=(TwoD& lhs, TwoD& rhs) {return !((lhs.x == rhs.x) && (lhs.y == rhs.y)) } bool operator==(const TwoD&) const TwoD(int i, int j) { x = i ; y = j} void output (ostream& outs) {outs << x << "\n" << y} void input (istream& ins) {ins >> x >> "\n" >> y}
int main() TwoD A(3, 5), B(4, 5) cout << "a = " A.output(cout) cout << endl cout << "b = " B.output(cout) cout << endl if (A != B) cout << "A not equal B" << endl if (A == B) cout << "A not equal B" << endl
Well, —, I don't know. There's no need to make != a friend function (== isn't a friend; that should have been a clue). You might want to argue that your colleague is learning C++ and so needs to at least look at friends. That's true, but one of the most important things to learn about friends is when not to use them, and the code you sent me is an excellent example of when they shouldn't be used.
Looking elsewhere in the code, the only thing I see obviously wrong is
Once this is fixed, either version of TwoD compiles with main(). I have no idea why your colleague got the error massages you sent me, or why the second TwoD worked but the first didn't, but I'll note that (apparently) a microsoft compiler is involved, which usually leads to nothing good.void input (istream& ins) {ins >> x >> "\n" >> y;}
x >> "\n"
is what's wrong, but it's not the problem. What's
the problem?
void output (ostream& outs) {outs << x << "\n" << y} void input (istream& ins) {ins >> x >> "\n" >> y}
main()
:
if (A != B) cout << "A not equal B" << endl if (A == B) cout << "A not equal B" << endl
gcc
Do?$ gcc -c bad.cc bad.cc: In member function 'void TwoD::input(std::istream&)': bad.cc:25: error: no match for 'operator>>' in '((std::istream*)ins)->std::basic_istream<_CharT, _Traits>::operator>> [with _CharT = char, _Traits = std::char_traits](((int&)(&((TwoD*)this)->TwoD::x))) >> "\012"' /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:131: note: candidates are: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_istream<_CharT, _Traits>& (*)(std::basic_istream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:134: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:137: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:169: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(bool&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:172: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(short int&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:175: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(short unsigned int&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:178: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(int&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:181: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(unsigned int&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:184: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(long int&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:187: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(long unsigned int&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:191: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(long long int&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:194: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(long long unsigned int&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:198: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(float&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:201: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(double&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:204: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(long double&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:207: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(void*&) [with _CharT = char, _Traits = std::char_traits ] /usr/lib/gcc/i386-redhat-linux/4.1.1/../../../../include/c++/4.1.1/istream:230: note: std::basic_istream<_CharT, _Traits>& std::basic_istream<_CharT, _Traits>::operator>>(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits ] $
$ gcc -c bad.cc bad.cc: In member function 'void TwoD::input(std::istream&)': bad.cc:25: error: no match for 'operator>>' in '((std::istream*)ins)-> std::basic_istream<_CharT, _Traits>::operator>> [with _CharT = char, _Traits = std::char_traits] (((int&)(&((TwoD*)this)->TwoD::x))) >> "\012"' /usr/include/c++/4.1.1/istream:131: note: candidates are: std::basic_istream<_CharT, _Traits>& [ and so on ]