operator overloading
Operator overloading is a form of C++ polymorphism. The previously described function overloading (defining multiple functions with the same name but different signatures) allows programmers to use functions with the same name to perform the same basic operations, even when those operations are applied to different data types.
Operator overloading extends the concept of overloading to operators, allowing multiple meanings to be given to C++ operators. (For example, using the * operator on an address will result in the value stored at that address, but applying it to two numbers will result in their product). C++ decides which operation to use based on the number and type of operands
C++ allows operator overloading to be extended to user-defined types.
To overload an operator, use a special form of function called an operator function, which has the following format:
operator op(argument-list)
For example, operator +() overloads the + operator, and operator *() overloads the * operator. op must be a valid C++ operator and cannot invent a new symbol
Computing Time: An Example of Operator Overloading
If 2 hours and 35 minutes were spent on Priggs' account and another 2 hours and 40 minutes in the afternoon, how much time was spent in total? This is similar in concept to addition, but the units being added (a mix of hours and minutes) do not match the built-in types.
First we use the regular method first, and then describe how to convert it into an overloaded operator
mytime0.h
#ifndef MYTIME0_H_
#define MYTIME0_H_
class Time
{
private:
int hours;
int minutes;
public:
Time();
Time(int h, int m = 0);
void AddMin(int m);
void AddHr(int h);
void Reset(int h = 0, int m = 0);
Time sum(const Time& t) const;
void Show()const;
};
#endif
The Time class provides methods for adjusting and resetting the time, displaying the time, and adding two times
mytime0.cpp
#include<iostream>
#include"mytime0.h"
Time::Time()
{
hours = minutes = 0;
}
Time::Time(int h, int m )
{
hours = h;
minutes = m;
}
void Time::AddMin(int m)
{
minutes += m;
hours += minutes / 60;
minutes %= 60;
}
void Time::AddHr(int h)
{
hours += h;
}
void Time::Reset(int h, int m )
{
hours = h;
minutes = m;
}
Time Time::sum(const Time& t)const
{
Time sum;
sum.minutes = minutes + t.minutes;
sum.hours = hours + t.hours + sum.minutes / 60;
sum.minutes %= 60;
return sum;
}
void Time::Show()const
{
std::cout << hours << " hours, " << minutes << " minutes";
}
Do not return references to local variables or temporary objects. After the function is executed, local variables and temporary objects will disappear, and references will point to non-existent data
usetime0.cpp
#include<iostream>
#include"mytime0.h"
int main()
{
using std::cout;
using std::endl;
Time planning;
Time coding(2, 40);
Time fixing(5, 55);
Time total;
cout << "planning time = ";
planning.Show();
cout << endl;
cout << "coding time = ";
coding.Show();
cout << endl;
cout << "fixing time = ";
fixing.Show();
cout << endl;
total = coding.sum(fixing);
cout << "coding.Sum(fixing) = ";
total.Show();
cout << endl;
return 0;
}
The final output of the program is
add addition operator
Converting the Time class to an overloaded addition operator is easy, just change the name of sum() to operator+().
Like sum(), operator+() is called by a Time object, it takes a second Time object as a parameter, and returns a Time object, so the operator+() method can be called like sum()
total = coding.operator +(fixing);
You can also use operator notation:
total = coding + fixing
Both notations will invoke the operator+() method. In operator notation, the object on the left side of the operator (here coding) is the calling object, and the object on the right side of the operator (here fixing) is the object passed as a parameter
operator +() The name of the function makes it possible to call it using function notation or operator notation. The compiler will decide what to do depending on the type of the operand:
int a,b,c;
Time A,B,C;
c = a + b; //use int addition
C = A + B; //use addtion as defined for Time objects
overload limit
Most C++ operators can be overloaded in this way, the overloaded operator does not have to be a member function, but at least one operand must be a user-defined type
1. Overloaded operators must have at least one operand of a user-defined type, which prevents users from overloading operators for standard types
2. When using an operator, the original syntactic rules of the operator cannot be violated (for example, the % operator cannot be overloaded to use an operand), and the priority of the operator cannot be modified.
3. Cannot create new operators
4. The following operators cannot be overloaded
- sizeof: The sizeof operator
- . : Membership operator
- .* : pointer to member operator
- :: : scope resolution operator
- ? : : conditional operator
- typeid: an RTTI operator
- const_cast: mandatory type conversion operator
- dynamic_cast: mandatory type conversion operator
- reinterpret_cast: mandatory type conversion operator
- static_cast: mandatory type conversion operator
Most operators in the table can be overloaded by member or non-member functions, but the following operators can only be overloaded by member functions
- =, the assignment operator
- ( ), the function call operator
- [ ], the subscript operator
- ->, the operator for accessing class members through pointers
Tomomoto
C++ controls access to private parts of class objects. Usually public class methods provide the only way to access, but sometimes this restriction is too strict, C + + provides another form of access
There are 3 kinds of friends
Friend function; Friend class; Friend member function;
By making a function a friend of a class, the function can be given the same access rights as the member functions of the class. Here we first introduce the friend function
create friend
The first step in creating a friend function is to place its prototype in the class declaration and precede the prototype declaration with the keyword friend:
friend Time operator*(double m, const Time & t);
The prototype means:
- Although the operator*() function is declared in the class declaration, it is not a member function, so it cannot be called using the member operator
- Although the operator*() function is not a member function, it has the same access rights as a member function
The second step is to write the function definition. Because it is not a member function, do not use the Time:: qualifier, and do not use the keyword friend in the definition, as defined below:
Time operator*(double m ,const Time & t)
{
Time result;
long totalminutes = t.hours * m * 60 + t.minutes *m;
result.hours = totalminutes / 60;
result.minutes = totalminutes % 60;
return result;
}
In short, the friend functions of a class are non-member functions, and their access rights are the same as those of member functions.
Commonly used friends: overloading the << operator
The << operator can be overloaded so that it can display the content of the object together with cout
1. The first overloaded version of <<
If the Time class knows to use cout, it must use a friend function. Because a statement like the following uses two objects, the first of which is an object of class ostream (cout):
cout<<trip;
If you use a Time member function to overload <<, the Time object will be the first operand, you must use << like this:
trip<<cout;
looks weird
But by using friend functions, operators can be overloaded like this
void operator<<(ostream &os, const Time &t)
{
os<<t.hours<<"hours,"<<t.minutes<<"minutes";
}
This allows the following normal-looking statement to be used
cout<<trip;
The new Time class declaration makes the operator<<() function a friend function of the Time class, but this function is not a friend of the ostream class
2. The second overloaded version of <<
There is a problem with the implementation presented earlier, a statement like the following works fine
cout<<trip;
but not allowed like usual cout with <<
cout<<"Trip time: "<<trip<<"Tuesday"; //can't do it
So modify the operator<<() function so that it returns a reference to the ostream object:
ostream & operator<<(ostream & os, const Time &t)
{
os<<t.hours<<"hours,"<<t.minutes<<"minutes";
return os;
}
Note that the return type is ostream&, that is, the function returns a reference to the ostream object
In general, to overload the << operator to display the object of c_name, a friend function can be used , which is defined as follows:
ostream & operator<<(ostream & os, const c_name &obj)
{
os<<...;
return os;
}
Operator overloading: as member function or non-member function
For many operators, you can choose to use member functions or non-member functions to implement operator overloading.
For example the overloaded + operator requires two operands. For the member function version, one operand is passed implicitly through the this pointer, and the other operand is passed explicitly as a function parameter; for the friend function version, both operands are passed as parameters
Non-member function overload "+"
Num operator+(const Num &m1,const Num &m2)
{
Num temp;
temp.n = m1.n + m2.n;
return temp;
}
Member function overload "+"
Num Num::operator +(const Num &t)
{
Num temp;
temp.n = n + t.n;
return temp;
}