Lecture notes for CS 503, Advanced Programming I

Advanced Programming I Lecture Notes

5 April 2007 • An Interlude


I Get E-mail

Date: Thu, 5 Apr 2007 09:44:16 -0400 (EDT)
Subject: Programming question
From: s-------@monmouth.edu
To: rclayton@monmouth.edu

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?).

The Error Messages

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)

The Code

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}

The Client

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

What's Wrong?

My Reply

Date: Thu, 5 Apr 2007 11:27:24 -0400
From: "R. Clayton"
To: s-------@monmouth.edu
Subject: Re: Programming question

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

void input (istream& ins) {ins >> x >> "\n" >> y;}
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.

What's The Problem?

What's 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]

$

What?

$ 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 ]

Points to Remember


This page last modified on 25 July 2006.

This work is covered by a
Creative Commons License.