Академический Документы
Профессиональный Документы
Культура Документы
Operator Overloading
Timothy Budd
Introduction
Almost all operators in C++ can be overloaded with new meanings. Operators may not look like functions but can hide function invocations. You cannot overload the meaning of operators if all arguments are primitive data types, nor can you change the precedence or associativity of operators.
Ch 7. Operator Overloading 2
| -== -= ^= ->
/ ! >> > /=
Ch 7. Operator Overloading
};
// define meaning of comparison for boxes bool operator < (box & left, box & right) { return left.value < right.value; }
Ch 7. Operator Overloading
Ch 7. Operator Overloading
Ch 7. Operator Overloading
10
class box { public: box (int v) : value(v) { } // prefix versions, ++aBox int operator ++ () { value++; return value; } int operator -- () { value--; return value; } int operator ++ (int) // postfix versions aBox++ { int result = value; // step 1, save old value value++; // step 2, update value return result; // step 3, return original } int operator -- (int) { int result = value; value--; return result; } private: int value; };
Ch 7. Operator Overloading 11
class box { public: ... const box & operator ++ () { value++; return *this; } } box mybox(3); mybox++++; // error - cannot increment constant value mybox+++= 7; // error - cannot assign to constant value mybox++ = 7; // error - cannot assign to constant value
Ch 7. Operator Overloading
12
Ch 7. Operator Overloading
13
Ch 7. Operator Overloading
14
ostream & operator << (ostream & out, const rational & value) { // print representation of rational number on an output stream out << value.numerator() << '/' << value.denominator(); return out; }
Ch 7. Operator Overloading
15
Ch 7. Operator Overloading
16
Always redefine the assignment operator in classes that include a pointer value.
const box & operator = (box & left, const box & right) { left.value = right.value; return left; } const box & operator = (box & left, int right) { left.value = right; return left; } box c; c = a; b = 2 + (a = 3);
Ch 7. Operator Overloading 17
const string string::operator = (const string & right) { if (this == right) // check for self assignment return right; ... }
Ch 7. Operator Overloading 18
Despite the use of the assignment symbol, constructors do not use the assignment operator.
box d = c; // uses copy constructor
If addition and assignment are both overloaded, then += should be overloaded as well.
Ch 7. Operator Overloading 19
class bigbox : public box { public: bigbox (int i, double d) : box(i), dvalue(d) { } void operator = (bigbox & right) { value = right.value; dvalue = right.dvalue; } protected: double dvalue; }; box a(3); bigbox b(3, 4.0); a = b; // legal, but sliced, box assignment, b = a; // not legal, argument must be a bigbox
Ch 7. Operator Overloading 20
const AnObject & operator += (AnObject & left, const AnObject & right) { AnObject sum = left + right; left = sum; return left; } Ch 7. Operator Overloading 21
The real vector data type does not check subscript ranges.
safeArray v(10); v[2] = 7; v[3] = v[2] + 12;
When returning a referenc, make sure that the value will continue to exist after the function exists.
Ch 7. Operator Overloading 23
LargerThan tester(12);
int i = ... ;
if (tester(i)) // true if i is larger than 12
A temporary object can be created by simply naming the class and any arguments to the constructor.
list<int>::iterator found = find_if (aList.begin(), aList.end(), LargerThan(12));
Ch 7. Operator Overloading 25
Ch 7. Operator Overloading
28
Mistakenly taping a comma instead of a period can be a very subtle programming error.
x = 7,12; class box { template <class T> const T & operator , (T & right) { return right; } };
Ch 7. Operator Overloading 29
An overloaded comma operator can never have the same short-circuit semantics as the original.
class box { public: box (int v) : val(v) { } int value () { return val; } int operator , (box & right) { return right.value(); } private: int val; };
Ch 7. Operator Overloading 30
Conversion Operators
Conversions from user types are defined by conversion operators; conversions to user types are defined by using constructors.
operator double (const rational & val) { return val.numerator() / (double) val.denominator(); }
rational r (2, 3); double d; d = 3.14 * double(r); // cast converts fraction to double
Ch 7. Operator Overloading 33
Ch 7. Operator Overloading
34
Ch 7. Operator Overloading
35
Disallowing Operators
An operator declared as private can be used only within a class definition.
class box { public: box (int v) : val(v) { } int value () { return val; } private: void operator = (box & right) { } }
box aBox (2); // create a new box box bBox (3); // and another
aBox = bBox; // error -- assignment is private
Ch 7. Operator Overloading 36
Ch 7. Operator Overloading
37
Ch 7. Operator Overloading
38
class emptyBox : public box { public: // constructors emptyBox () : box() , aField() { } emptyBox (const emptyBox & right) : box(right), aField(right.aField) { } ~emptyBox() // destructor { // implicit deletion of aField // implicit call on parent class destructor } const emptyBox & operator = (const emptyBox & right) {// operators aField = right.aField; box::operator = (right); return *this; } emptyBox * operator & () { return * this; } template <class T> const T & operator , (const T & right) { return right; } private: box aField; };
Ch 7. Operator Overloading 39
Implicit Constructors
If no constructor are specified, an implicit default constructor constructor will be created. First, invoke the default constructor for the parent class if the current class was formed by using inheritance. The function will recursively apply default initialization rules for every data field. An implicit copy constructor is created if no other copy constructor is specified, even if other constructors have been defined.
Ch 7. Operator Overloading 40
Implicit Destructors
First, invoke destructors for every data field and then invoke the destructor for the parent class. Fields are destroyed in the opposite order listed in the class body. An implicit destructors is never considered virtual.
Ch 7. Operator Overloading 41
Ch 7. Operator Overloading
42
Ch 7. Operator Overloading
43
Ch 7. Operator Overloading
44
class box { public: box () { value = 0; } box (int i) { value = i; } box (box & a) { value = a.value; } ~box() { } // destructor void operator = (box & right) { value = right.value;} operator int () { return value; } private: int value; }; box operator + (box & left, box & right) { return box(((int) left) + (int) right); }
Ch 7. Operator Overloading 45
int foo (box abox) { box bbox; bbox = abox + 1; return bbox; } int main() { box mybox(3); mybox = 4; mybox = foo (mybox + 1); return 0; }
Ch 7. Operator Overloading 46
box mybox(3); // integer constructor mybox = 4; // integer constructor to create temporary // assignment of temporary to variable // destructor on temporary mybox = foo (mybox + 1); // start of statement // integer constructor to create temporary // binary addition of boxes
return box(((int) left) + (int) right); // inside addition operator // conversion of left box to integer // conversion of right box to integer // integer constructor for temporary // return from addition operator mybox = foo (mybox + 1); // continuation of statement box bbox; // inside function foo // default constructor to create variable
Ch 7. Operator Overloading 47
bbox = abox + 1; // start execution // integer constructor to create temporary for constant // binary addition operator for boxes box operator + (box & left, box & right) return box(((int) left) + (int) right); // inside addition operator // conversion of left box to integer // conversion of right box to integer // integer constructor for temporary bbox = abox + 1; // continue execution // assignment for boxes // destructor for temporary // conversion from box to integer // destructor for local variable bbox // return from function // destructor for temporary argument mybox = foo (mybox + 1); // continuation of statement // integer constructor converting result to box // assignment operation // destructor of temporary value // destructor of variable mybox
Ch 7. Operator Overloading 48
class string { public: // constructors string (char * c) ... string (const string & s) ... string (int i) ... }; string aString = 'a'; class string { public: // constructors string (char * c) ... string (const string & s) ... explicit string (int i) ... }; Ch 7. Operator Overloading
49