Choosing Member or Nonmember Implementation

When we define an overloaded operator, we must decide whether to make the operator a class member or an ordinary nonmember function. In some cases, there is no choice—some operators are required to be members; in other cases, we may not be able to define the operator appropriately if it is a member.

The following guidelines can be of help in deciding whether to make an operator a member or an ordinary nonmember function:

• The assignment (=), subscript ([]), call (()), and member access arrow (->) operators must be defined as members.

• The compound-assignment operators ordinarily ought to be members. However, unlike assignment, they are not required to be members.

• Operators that change the state of their object or that are closely tied to their given type—such as increment, decrement, and dereference—usually should be members.

• Symmetric operators—those that might convert either operand, such as the arithmetic, equality, relational, and bitwise operators—usually should be defined as ordinary nonmember functions.

Programmers expect to be able to use symmetric operators in expressions with mixed types. For example, we can add an int and a double. The addition is symmetric because we can use either type as the left-hand or the right-hand operand. If we want to provide similar mixed-type expressions involving class objects, then the operator must be defined as a nonmember function.

When we define an operator as a member function, then the left-hand operand must be an object of the class of which that operator is a member. For example:

string s = "world";
string t = s + "!";  // ok: we can add a const char* to a string
string u = "hi" + s; // would be an error if + were a member of string

If operator+ were a member of the string class, the first addition would be equivalent to s.operator+("!"). Likewise, "hi" + s would be equivalent to "hi".operator+(s). However, the type of "hi" is const char*, and that is a built-in type; it does not even have member functions.

Because string defines + as an ordinary nonmember function, "hi" + s is equivalent to operator+("hi", s). As with any function call, either of the arguments can be converted to the type of the parameter. The only requirements are that at least one of the operands has a class type, and that both operands can be converted (unambiguously) to string.


Exercises Section 14.1

Exercise 14.1: In what ways does an overloaded operator differ from a built-in operator? In what ways are overloaded operators the same as the built-in operators?

Exercise 14.2: Write declarations for the overloaded input, output, addition, and compound-assignment operators for Sales_data.

Exercise 14.3: Both string and vector define an overloaded == that can be used to compare objects of those types. Assuming svec1 and svec2 are vectors that hold strings, identify which version of == is applied in each of the following expressions:

(a) "cobble" == "stone"

(b) svec1[0] == svec2[0]

(c) svec1 == svec2

(d) "svec1[0] == "stone"

Exercise 14.4: Explain how to decide whether the following should be class members:

(a) %

(b) %=

(c) ++

(d) ->

(e) <<

(f) &&

(g) ==

(h) ()

Exercise 14.5: In exercise 7.40 from § 7.5.1 (p. 291) you wrote a sketch of one of the following classes. Decide what, if any, overloaded operators your class should provide.

(a) Book

(b) Date

(c) Employee

(d) Vehicle

(e) Object

(f) Tree


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset