[C++] Chap 08 - Operator Overloading, Friends, and References
Operator Overloading
- Operators (
+, -, %, ==, ...) are just functions - think of it as
+(x, 7)(+is the function name,x, 7are the arguments, returns sum of its arguments)
1. Via Non-member, non-friend of a class
const Money operator +(const Money& amount1, const Money& amount2);
// const reference parameters for efficiency
// return type is Money
- Overloaded
+above is NOT a member function of the class - Need to use accessor and mutator function since the overloaded function is not member function of the class
const Money operator +(const Money& amount1, const Money& amount2) {
return Money(foo, bar);
}
// returns money class
- Constructor is not a void function. It return the class object itself but without given name.
- Called an ‘anonymous object’
Returning by const value
- Returning by const value : return value is also a class object, if we don’t put
constmodifier, we can do things(calls the member function, etc…) unintentionally
(m1+m2).output(); //Legal
(m1+m2).input(); // Legal but it changes the value of anonymous object
//Wierd
- To prevent those things to happen, we return by
constvalue - Then,
(m1+m2).input()will produce a compile error - Putting
constwill do automatic error checking - Changing
(m1+m2)will cause a problem when the returned object is reference
Overloading Unary Operators
const Money operatror -(const Money& amount);
- One argument (since 1 operand)
-opeartor can be overloaded twice : for binary, unary operator
2. Via member of a class
- When overloaded function is a ‘member operator’, calling object serves as the first parameter
class Money{
public:
const Money operator +(const Money& amount2) const;
const Money operator -() const;
};
const Money Money::operator +(const Money& amount2) const {
int allCents1 = cents + dollors * 100;
//private member variables of the calling objects are accessed
int allCents2 = amount2.cents + amount2.dollars * 100;
//also private member variables of any object of the same class can be also accessed
...
}
const Money Money::operator -() const {
return Money(-dollars, -cents);
} //No argument!
Other overloads
- Function call opeartor
()- Must be overloaded as a member function
- Can overload for any number of arguments
class Money {
public:
const Money operator ()(int a) const;
};
const Money Money::operator ()(int a) {
}
&&, ||operator : recall short-circuit evaluation.anObject(42)can be thought of asanObject.()(42)
Automatic Type Conversion
- Even if we don’t overload operator with
intoperand, it is legal if we provide constructors for automatic type conversion
Money baseAmount(100, 60), fullAmount;
fullAmount = baseAmount + 25; // automatic type conversion happens
// fullAmount = 25 + baseAmount; // does not work
fullAmount.output();
Money::Money(int theDollars) : dollars(theDollars), cents(0) {}
// if provide constructors for automatic type conversion
- To make
25+baseAmountpossible, must define as non-member function. (since member function regards first argument as the class object itself (calling obj).) Money+Moneyoperator overloaded +Money(int)constructor overloaded =Money+intpossible- But typically
int+Moneyis impossible for overloading via member function
3. Via non-member, friend of a class
- Overload operator as a nonmember
- Automatic type conversion of all arguments
- Causes inefficiency (Must use accessor or mutator, can’t access to private)
- Overload operator as a member
- Gives efficiency of bypassing accessor and mutator
- Asymmetry in automatic type conversion
Friend functions
- Friends can directly access private class data : no overhead, more efficient
- Use keyword
friendin front of the function declarationfriendkeyword not used in function definition
- Can be located anywhere(
public, private, protected) in the class definition - Since it is not member function, parameter list is similar as nonmember overloading operators
- Operator overloading is the most common usage of friend function but any function can be a friend of a class
// 1. Non-member, 3. Friend
const Money operator +(const Money& amount1, const Money& amount2);
// 2. Member
class Money{
public:
const Money operator +(const Money& amount2) const;
// 3. Friend
friend const Money operator +(const Money&, const Money&);
// also inside the class definition
//but not considered as a member function
};
const Money Money::operator + (const Money& amount2) const {
}
Friend Classes
- Entire classes can be a friend of other class
- eg) class F is friend of class C
class F; // forward declaration
class C
{
public :
friend class F;
};
class F
{
...
};
- All member functions of F are friends of C
- NOT reciprocated (single direction)
- Violates the pure spirit of OOP but for operators : very advantageous (automatic type conversion)
- Still encapsulates (because friend is in the class definition)
References
- Name of a storage location
- Similar to “pointer”
int robert;
int& bob = robert;
bobis a reference to storage location forrobert- Changes made to bob will affect robert
- Returning by a reference
- Allows some operator overload implementations (i.e.
<<or>>) - Do not return local variable by reference (dangling reference)
- Allows some operator overload implementations (i.e.
L-Value and R-Value
- If you want the object returned by a function to be an L-value, it must be returned by reference
class Employee {
public:
Money& getSalary() {return salary;}
const Money& getSalaryNew() {return salary;}
...
private:
Money salary;
...
};
int main() {
Employee joe;
joe.getSalary().input();
//can access and manipulate private member variable
joe.getSalaryNew().input(); //illegal
- Returning a class-type can be efficient when return by reference
- But private member can be easily manipulated
constcan protect this from happening
Overloading >> and <<
- Insertion operator,
<<- Used with
cout - A binary operator
cout<<"Hello";: Firest operand is predefined objectcout, second operand is string “Hello”
- Used with
- What value should
<<return? : thecoutobject
class Money
{
public:
friend ostream& operator <<(ostream& outputStream, const Money& amount);
friend istream& operator >>(istream& inputStream, Money& amount);
};
//Note : << and >> cannot be a member operator
//(the first operand is not the class obejct)
- Can chain
<<or>>because the operator returns by the reference - since
<<is not intended to change the original object, useconstand call-by-reference while>>uses only call-by reference
Four types of returned value to use
- By plain old value
T f( ); - By const
const T f( ); - By reference
T& f( ); - By const reference
const T& f( );- For simple types , no point in using
const. - If you want the simple value returned to be l-value, then return by reference
- For simple types , no point in using
int foo();
const int foo(); //unnecessary
int& foo(); //returns aliases or reference
const int& foo(); //returns reference but cannot be modified via this function
- Returning a local variable by reference is problematic
const Tandconst T&are very similar : theconstmodifier- But using
const Tis more preferred : because of hazard of dangling reference (local parameter returned by reference)
Assignment operator =
- Must be overloaded as a member operator
- Automatically overloaded
- The default assignment operator performs the member-wise copy.
- Member variables from one object → corresponding member variables from other
Increment and Decrement
- Two version : prefix, postfix
- For compilers to distinguish two verisons of operator, add dummy 2nd parameter of type
int
IntPair operator ++(); //Prefix
IntPair operator ++(int); //Postfix
Overloading []
- Need to be a member function
- Need to return reference to use the operator at the left-hand side of
=
class CharPair
{
public:
char& operator[] (int index);
}
char& CharPair::operator[] (int index)
{
...
}
int main() {
CharPair a;
a[1]= 'A';
//For l-value, output must be reference
cout<<a[1];
}
댓글을 불러오는 중입니다.