Chapter 11 - Using Classes

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;
}

Guess you like

Origin blog.csdn.net/yangSHU21/article/details/131676869