Operator overloading operation in C++

. Operator overloading
Sometimes it is hoped that these operators can be used to perform operations between objects, in order to achieve the purpose of making the program more concise and easy to understand. For example, complex numbers can perform four arithmetic operations. If the addition of two complex number objects can be done directly with the + operator, wouldn't it be intuitive and concise?

Operator overloading is aimed at the actual needs of new types of data, and appropriately transforms the original operators.

Implementation is achieved by function, to reload into non-static member function of a class and overload a non-member function (reason: not all operators can be overloaded in a class in the body). The essence is to write a function with an operator as the name .

The C++ language supports various relational operators (<,>, <=, >=, ==, etc.), which can be used to compare C++ built-in data types.
You can override other "." "*" "::" "?:"outside any relational operator, after the operator overloading relationship can be used to compare an object class.
After overloading, the precedence and associativity of operators will not change.

1. The binary operator is overloaded as a member function
. Format

函数类型 operator 运算符(形参)
{
    
    
  ……
}
参数个数=原操作数-1(后置++--除外)

Rules
To reload the operator B to a class member function, so that expression can be achieved oprd1(操作数1) B oprd1(操作数1), wherein, oprd1 class object is A, then B should be overloaded operator member function of class A, the parameter type should be oprd2 The type it belongs to.

After overloading, the expression oprd1 B oprd1is equivalent tooprd1.operator B(oprd2)

Example: The addition and subtraction operations of complex numbers are overloaded as member functions.
Requirements:.
The + and-operators are overloaded as member functions of the complex number .
Rules:. The
real and imaginary parts are added and subtracted separately
. Operands:.
Both operands are both Plural objects

Code:
header file

class Complex
{
    
    
public:
	Complex(double r = 0.0, double i = 0.0) :real(r), imag(i) {
    
    };
	//运算符+重载成员函数
	Complex operator +(const Complex& c2)const;
	//运算符+重载成员函数
	Complex operator -(const Complex& c2)const;
	//输出复数
	void display()const;
private:
	double real;//实部
	double imag;//虚部
};

CPP :

Complex Complex::operator+(const Complex& c2) const
{
    
    
    //创建一个临时无名对象作为返回值
    return Complex(real+c2.real,imag+c2.imag);
}

Complex Complex::operator-(const Complex& c2) const
{
    
    
    //创建一个临时无名对象作为返回值
    return Complex(real - c2.real, imag - c2.imag);
}

void Complex::display() const
{
    
    
    cout << "(" << real << "," << imag << ")" << endl;
}

Main function

int main()
{
    
    
	Complex c1(5, 4), c2(2, 10), c3;
	cout << "c1=";c1.display();
	cout << "c2=";c2.display();
	c3 = c1 - c2;//使用运算符重载完成复数减法
	cout << "c3=c1 - c2=";c3.display();
	c3 = c1 + c2;//使用运算符重载完成复数减法
	cout << "c3=c1 + c2=";c3.display();
	return 0;
}

result:

c1=(5,4)
c2=(2,10)
c3=c1 - c2=(3,-6)
c3=c1 + c2=(7,14)

2. Unary operator overloading is a member function
. Pre-unary operator overloading rules
If you want to overload U as a class member function, so that it can realize expressions U oprd(操作数), where oprd is an object of class A, then U should be overloaded as class A The member function has no formal parameters .

After overloading, the expression U oprdis equivalent tooprd.operator U()

. Post-unary operator ++ and – overloading rule
If you want to overload U as a class member function, so that it can realize expression oprd(操作数)++or oprd(操作数)--, where oprd is an object of class A, then ++ or – should be overloaded as A The member function of the class, and has an int type parameter .

After overloading, the expression oprd++is equivalent tooprd.operator ++(0)

Example: Overload the pre-++ and post-++ as member functions of the clock class.
Pre-unary operator, overloaded function has no formal parameter.
Post-++ operator, overloaded function requires an int parameter
operation The number is an object of the clock class, and the
time is increased by 1 second

Code:
header file

class Clock
{
    
    
public:
	Clock(int hour=0,int minute=0,int second=0);
	void showTime()const;
	//前置单目运算符重载
	Clock& operator ++();
	//后置单目运算符重载
	Clock operator ++(int);
private:
	int hour, minute, second;
};

CPP

Clock::Clock(int hour, int minute, int second)
{
    
    
	if(0<=hour&&hour<24&&0<=minute&&minute<60 && 0 <= second && second < 60)
	{
    
    
		this->hour = hour;
		this->minute = minute;
		this->second = second;
	}
	else
	{
    
    
		cout << "Time error!"<<endl;
	}
}
//显示时间
void Clock::showTime() const
{
    
    
	cout << hour << ":" << minute << ":" << second << endl;
}

Clock& Clock::operator++()
{
    
    
	second++;
	if(second>=60)
	{
    
    
		second -= 60;
		minute++;
		if(minute>=60)
		{
    
    
			minute -= 60;
			hour = (hour + 1) % 24;
		}
	}
	return *this;
}

Clock Clock::operator++(int)
{
    
    
	//注意形参表中的整型参数
	Clock old = *this;
	++(*this);
	return old;
}

Main function

int main()
{
    
    
	Clock myClock(23, 59, 59);
	cout << "First time output:";
	myClock.showTime();
	cout << "Show myClock++:  ";
	(myClock++).showTime();
	cout << "Show ++myClock:  ";
	(++myClock).showTime();
	return 0;
}

result

First time output:23:59:59
Show myClock++:  23:59:59
Show ++myClock:  0:0:1

3. Operator overloading is a non-member function
. Reasons that cannot be used as a class member function
1. The left operand is not an object of this class (such as a real number plus a complex number)
2. The left operand is an object of the class but the class is not specified by the programmer (such as a class library) Class)

. Rule
1. The formal parameters of a function represent the operands arranged in order from left to right

2. When overloading is a non-member function
. The number of parameters = the number of original operands (post ++, except -)
. There should be at least one parameter of a custom type

3. For overloaded functions of post-barrage operators ++ and -, an int must be added to the parameter list, but the parameter name does not need to be written

4. If you need to manipulate the private members of a certain type of object in the overloaded function of the operator, you can declare this function as a friend of that class

""" After the
binocular operator B is overloaded, the expression is oprd1 B oprd2
equivalent tooperator B(oprd1,oprd2)

After the pre-unary operator B is overloaded, the expression is B oprd
equivalent toB oprd

After the post-unary operators ++ and – are overloaded, the expression is oprd B
equivalent tooperator B(oprd,0)

Example: overloading the addition and subtraction of Complex and the "<<" operator are non-member functions
. Overloading + and-(binocular) as non-member functions, and declaring them as friends of the complex number class, two operations Numbers are often quoted in plural types.
. Overload << (binocular) as a non-member function and declare it as a friend of the plural class. Its left operand is a std::ostream reference, and the right operand is a constant reference of the plural class, returning std ::ostream reference to support the following output:
cout<<a<<b;
the output calls:
operator<<(operator<<(cout,a),b)

head File

class Complex
{
    
    
public:
	Complex(double r = 0.0, double i = 0.0) :real(r), imag(i) {
    
    };

	friend Complex operator +(const Complex& c1, const Complex& c2);
	friend Complex operator -(const Complex& c1, const Complex& c2);
	friend ostream& operator<<(ostream& out, const Complex& c);
private:
	double real;//实部
	double imag;//虚部
};

CPP

Complex operator+(const Complex& c1, const Complex& c2)
{
    
    
	return Complex(c1.real+c2.real,c1.imag+c2.imag);
}

Complex operator-(const Complex& c1, const Complex& c2)
{
    
    
	return Complex(c1.real - c2.real, c1.imag - c2.imag);
}

ostream& operator<<(ostream& out, const Complex& c)
{
    
    
	out << "(" << c.real << "," << c.imag << ")";
	return out;
}

Main function

int main()
{
    
    
	Complex c1(5, 4), c2(2, 10), c3;
	cout << "c1=" << c1 << endl;
	cout << "c2=" << c2 << endl;
	c3 = c1 - c2;
	cout << "c3 = c1 - c2=" << c3 << endl;
	c3 = c1 + c2;
	cout << "c3 = c1 + c2=" << c3 << endl;
	return 0;
}

result

c1=(5,4)
c2=(2,10)
c3 = c1 - c2=(3,-6)
c3 = c1 + c2=(7,14)

Four, C++ overload () (forced type conversion operator) the
following reference: https://blog.csdn.net/qq_27278957/article/details/85269245
In C++, the name of the type (including the name of the class) itself is also a An operator, that is, the type casting operator.

The type coercion operator is a unary operator and can also be overloaded, but it can only be overloaded as a member function, not as a global function. After proper overloading, the (type name) object, the expression that casts the type of the object, is equivalent to the object.operator type name (), that is, it becomes a call to the operator function.

The following program overloads the double type coercion operator.

#include <iostream>
using namespace std;
class Complex
{
    
    
    double real, imag;
public:
    Complex(double r = 0, double i = 0) :real(r), imag(i) {
    
    };
    operator double() {
    
     return real; } //重载强制类型转换运算符 double
};
int main()
{
    
    
    Complex c(1.2, 3.4);
    cout << (double)c << endl; //输出 1.2
    double n = 2 + c; //等价于 double n = 2 + c. operator double()
    cout << n; //输出 3.2
}

The output of the program is:

1.2
3.2

Line 8 overloads the double operator. When overloading the cast operator, you do not need to specify the return value type, because the return value type is determined, which is the type represented by the operator itself, which is double in this case.

The effect after overloading is that (double)c in line 13 is equivalent to c.operator double().

With the overload of the double operator, where a variable or constant of type double should appear, if an object of type Complex appears, then the operator double member function of the object will be called, and its return value will be taken use.

For example, in line 14, the compiler believes that if double type data appears in the position of c in this line, it can be interpreted, and the Complex class just overloads the double operator, so this line is equivalent to:

double n = 2 + c.operator double();

Five, C++ operator overloading precautions and summary
When performing operator overloading in C++, there are the following issues that need to be paid attention to:

1. The meaning of the operator after overloading should conform to the original usage habits. For example, overloading the + operator, the completed function should be similar to doing addition, it is not appropriate to do subtraction in the overloaded + operator. In addition, overloading should try to retain the original characteristics of the operator.
2. C++ stipulates that operator overloading does not change the priority of operators.
3. The following operators cannot be overloaded: ., .*, ::, ?:, sizeof.
4. When overloading operators (), [], ->, or assignment operator =, they can only be overloaded as member functions, not global functions.

The essence of operator overloading is to overload the operator as a function, and the expression using the operator is interpreted as a call to the overloaded function.

Operators can be overloaded as global functions. At this time, the number of parameters of the function is the number of operands of the operator, and the operands of the operator become the actual parameters of the function.

Operators can also be overloaded as member functions. At this time, the number of parameters of the function is the number of operands of the operator minus one. One of the operands of the operator becomes the object of the function, and the rest become the actual parameters of the function.

The assignment operator = needs to be overloaded when necessary to avoid the pointers inside the two objects pointing to the same piece of storage space.

Operators can be overloaded as global functions and then declared as friends of the class.

<< and >> are overloaded in iostream and become the so-called "stream insertion operator" and "stream extraction operator".

The name of the type can be used as a cast operator, or it can be overloaded as a member function of the class. It can cause the object to be automatically converted to a certain type.

There are two overloading methods for the increment and decrement operators, which are used to distinguish the pre-use and post-use.

Operator overloading does not change the priority of operators. When overloading an operator, you should try to preserve the original characteristics of the operator.

Guess you like

Origin blog.csdn.net/qq_43530773/article/details/113995171