![]() |
![]() |
![]() |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
![]() |
![]() |
To access the contents, click the chapter and section titles.
C++ in Plain English
Like the CStr addition functions, these operator functions return an object by value. Consequently, they follow the same basic steps: create a new object, set some values, and return the object as a value. (The last step implicitly calls the classs copy constructor.) CTemp_point CTemp_point::operator+(double temp_diff) { CTemp_point new_pt(*this); new_pt.temp += temp_diff; return new_pt; } CTemp_point CTemp_point::operator-(double temp_diff) { CTemp_point new_pt(*this); new_pt.temp -= temp_diff; return new_pt; } The last function I added to the class is the assignment operator. This function is unnecessary, because it implements assignment in the same way that the compiler would implement assignment by default. However, its still useful as an example. This approach uses a simple member-by-member copy from the right operand (translated into the argument, pt) to the left operand (the object through which the function is called). As with almost all assignment functions, the last line of the function is return *this. CTemp_point& CTemp_point::operator=(const CTemp_point &Pt) { x = pt.x; y = pt.y; z = pt.z; temp = pt. temp; return *this; } Forging Ahead with Operator OverloadingBelieve it or not, weve only started covering the subject of operator overloading. The subject has a number of fine points (some of which you may not use for years) that Ill leave for Part II. But there are some major points that you should keep in mind when experimenting with operator functions. This section is both a summary and an overview of some points not yet covered. Using the this PointerMany operator functions use this, a C++ keyword not supported in C. Within a member function, this is a pointer to the current object. (In this context, current object is the object through which the function was called.) The keyword is often useful in operator functions, because it provides a way to apply the copy constructor to the current object or return the current object as a value. Naming an Operator FunctionOperator functions follow a simple naming scheme. For any given operator @, the name of the function is operator@. The exception is conversion functions, for which the name is: operator type Binary OperatorsWhen the compiler evaluates an expression of the form obj1@obj2, it translates the expression into the function call: obj1.operator@(obj2) if this function is defined within obj1s class, or the compiler translates the expression into the function call: operator@(obj1, obj2) in which the function is defined outside any class. Declaring it as a friend of a class gives the function access to all members. The advantage of using the latter form is that it makes it possible to implement the same operation regardless of whether obj1 appears on the right or the left of the operator. To support the reverse order, write a separate function: operator@(obj2, obj1) If the declaration of obj2s class is supplied by someone else (for example, if obj2 has a standard type such as int or char*), this is the only way to define this operation. Unary OperatorsWhen the compiler evaluates an expression of the form @obj1, it translates the expression into the function call: obj1.oporator@() if this function is defined within obj1s class, or the compiler translates the expression into the function call: operator@(obj1) in which the function is defined outside any class. Declaring it as a friend of a class gives the function access to all members. As an example, unary minus (-) can be defined for the CTemp_point class, in which the effect is to reverse the sign of the temp data member: class CTemp_point { ... CTemp_point operator-(); }; CTemp_point CTemp_point::operator-() { CTemp_point new_point(*this); new_point.temp *= -1; return new_point; } As with all operator functions (except conversion), the return type must be declared explicitly. The compiler can make no assumptions here. You can define an operation on class A, for example, so that it returns an object of any type you wish. The Assignment OperatorThe assignment operator defines how to assign an object from another object of the same class. Although assignment is a binary operator like any other, it has some special restrictions. The assignment function must be defined as a member function with the following declaration: class& operator=(conat class &arg) The function is called as a member function of the left operand of an assignment, and the right operand is the argument. The final task of an assignment function is to return the left operand, which it does by using the this pointer: return *this; Assignment from Other TypesAn assignment function determines how the compiler assigns a value to an object from another object of the same class. There is no valid assignment function that involves assignment from another type. Instead, the compiler calls the appropriate constructor or conversion function, if available, to convert from one data type to another. CHorse Stacy, sugar; Stacy = sugar; // Calls CHorse::operator= Stacy = fast; // Calls CHorse::CHorse(char*) *char name = sugar; // Calls CHorse::operator char* Other Assignment Operators (+=, -=, etc.)You might think that if you define both addition (+) and assignment (=) for a given class, the addition-assignment operator (+=) is automatically defined, but this is not the case. Each assignment operator (such as +=, -=, *=, and so on) is considered a separate operator, and if you want to support it, you need to write another function. For example, the following code implements += for the CStr class. (Because of its small size, by the way, it is a good candidate for function inlining.) class CStr { ... CStr& operator+=(CStr &str); }; CStr& CStr::operator+=(CStr &str) { cat(str.get()); return *this; } Associativity, Prcedence, and CommutativityThe rules of associativity and precedence determine which operations are performed before others, C++ follows the standard rules when you define operators for your own classesin other words, C++ applies the same associativity and precedence rules to your class that it applies to standard types such as int and float. For example, suppose you have defined both addition (+) and multiplication (*) between CStr objects and that the compiler is evaluating the following statements: CStr stringA, stringB, stringC; stringA = stringA * stringB + stringA * stringC; The compiler evaluates this last statement as though it were written as: stringA = (stringA * stringB) + (stringA * stringC); Commutativity is a property some operators have in which the left-to-right order of the operands does not matter. Not all C++ operators have this property, but addition and multiplication do when applied to the standard types. However, commutativity of addition and multiplication does not automatically extend to user-defined classes. These operations are commutative only if you write them that way. Furthermore, you have to write operations such as operator+(CStr, char*) and operator+ (char*, CStr) as separate functions, although it is legal to save space by having one function call the other. CStr operator+(char* s, CStr &str) { return operator+(str, s); }
|
![]() |
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement. |