Path: utzoo!mnetor!tmsoft!torsqnt!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!zaphod.mps.ohio-state.edu!pacific.mps.ohio-state.edu!linac!att!ucbvax!pasteur!galileo.berkeley.edu!jbuck From: jbuck@galileo.berkeley.edu (Joe Buck) Newsgroups: comp.lang.c++ Subject: Re: Class members flexible enough? Message-ID: <11461@pasteur.Berkeley.EDU> Date: 26 Feb 91 19:54:06 GMT References: <1991Feb22.190313.4936@intellistor.com> Sender: news@pasteur.Berkeley.EDU Reply-To: jbuck@galileo.berkeley.edu (Joe Buck) Distribution: na Lines: 94 In article <1991Feb22.190313.4936@intellistor.com>, wicklund@intellistor.com (Tom Wicklund) writes: |> I've been looking at a few implementations of class "complex" recently |> and wonder current C++ class members are sufficient. They are. Your example is a poor design of the "complex" class. In fact, friend functions are not needed at all. I recommend that you define class Complex something like this: class complex { private: double re; double im; public: // constructors complex() : re(0), im(0) {} complex(double r) : re(r), im(0) {} complex(double r, double i) : re(r), im(i) {} complex(const complex& c) : re(c.re), im(c.im) {} // assignment operators complex& operator=(const complex& c) { re = c.re; im = c.im; return *this; } complex& operator+=(const complex& c) { re += c.re; im += c.im; return *this; } // -=, *=, /= defined similarly }; inline complex operator+ (const complex& a, const complex& b) { complex tmp(a); return tmp += b; } // -, *, / defined similarly. NOTICE: operator+ is NOT a friend. It only accesses public operations of class complex. An approach like this is used in the Gnu library, and is advocated by Andrew Koenig in his tutorials. Notice the structure of the operator+ function above. Notice that it expresses the logical relation between the + operator and the += operator in a very clean way. In fact, it could be implemented as a template, once these are added to the language. On that glorious day one can write template inline T operator+ (const T& a, const T& b) { T tmp(a); return tmp += b; } and instantly, any class with a += operator has a corresponding + operator (see chapter 14 of E&S for a discussion of templates). |> These implementations bring up the questions: |> |> 1. Why aren't member functions used? In the ATT case my guess is |> that the friend implementation allows automatic int/float |> conversion to complex on either side of the operator. A member |> function "operator +" won't convert the left hand argument |> automatically. In the GNU case it looks like somebody decided to |> implement these functions independent of class representation |> (the implementation is in terms of public functions and a |> constructor). Your guess is correct; in both cases a symmetrical + operator results (it can add int, double, float, complex in any combination). The GNU case is doing it the right way. Member functions of an object are functions that operate on that object. + does not operate on a single object, it takes two arguments and produces an output that is a function of both and changes neither. It can be cleanly defined in terms of the += primitive. |> 2. If member functions aren't powerful enough to implement a class |> like complex, is the language lacking something? The whole |> concept of friend functions seems to point to missing language |> facilities. As the GNU case shows, friends are not needed at all. Some people think everything should be done with member functions. This is misguided, in my view. Member functions define the interface of a class. More complex operations that can be defined efficiently using class primitives shouldn't be member functions, in my view; they should be what Grady Booch calls "free subprograms". -- Joe Buck jbuck@galileo.berkeley.edu {uunet,ucbvax}!galileo.berkeley.edu!jbuck