C++ operator overloading as non-member function

Operators can also be overloaded as non-member functions. At this time, the operands required by the operation need to be passed through the formal parameter table of the function, and the order of the formal parameters from left to right in the formal parameter table is the order of the operator operands. If you need to access private members of the operator argument object, you can declare the function as a friend function.

[Hint] Do not mechanically declare the non-member function of the overloaded operator as a friend function of the class, only do so when you need to access the private or protected members of the class. If it is not declared as a friend function, the function only depends on the interface of the class, as long as the interface of the class does not change, the implementation of the function does not need to change; if it is declared as a friend function, the function will depend on the class Even if the interface of the class does not change, as long as the setting of the private data member of the class changes, the implementation of the function needs to be changed.

For the binary operator B, if b1 B b2 is to be implemented, as long as one of b1 and b2 has a custom type, B can be overloaded as a non-member function, and the formal parameters of the function are b1 and b2. After overloading, the expression b1 B b2is equivalent to a function call operator B(b1,b2).

For the pre-unary operator U, such as "-" negative sign, etc., if you want to realize the expression U b, where b has a self-defined type, you can overload U as a non-member function, and the formal parameter of the function is b. After overloading, the expression U bis equivalent to a function call operator U(b).

For post-post unary operators ++ and –, if the expression b++ or b– is to be realized, where b is a self-defined type, then the operator can be overloaded as a non-member function. At this time, the function has two formal parameters, one is b, and the other is an int parameter. The second parameter is used to distinguish from the pre-operator overloaded function. After overloading, expressions b++and b--are equivalent to function calls operator++(b,0)andoperator--(b,0)

[Example] Overloading the addition and subtraction operations and the "<<" operator of Complex in the form of non-member functions

Overload the operators "+" and "-" as non-member functions, and declare them as friend functions to realize the addition and subtraction of complex numbers. The overloaded operator "<<" can use the "<<" operator on cout to output a Complex object, making the output more convenient and intuitive.

//将加减运算符重载为非成员函数
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& c3, const Complex& c4);
	friend ostream& operator<<(ostream& out, const Complex& c);
	void display() const;
private:
	double real;
	double imag;
};

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 << ")" << endl;
	return out;
}


int main()
{
    
    
	Complex c1(5, 4);

	Complex c2(2, 10);

	Complex c3;

	cout << "c1=" << c1 << endl;	

	cout << "c2=" << c2 << endl;

	c3 = c1 + c2;
	cout << "c3=c1+c2=" << c3 << endl;

	Complex c4;
	c4 = operator-(c2,c1);
	cout << "c4=c2-c1=" << c4 << endl;

	Complex c5;
	c5 = 5.0 + c1;
	cout << "c5=5.0+c1=" << c5 << endl;

	return 0;
}

operation result:
insert image description here

Analysis:
To overload an operator as a non-member function of a class, the operands must be passed to the operator overloading function by means of formal parameters. Because the operator is overloaded as a non-member function of the class, it cannot access the private members of the class, so the non-member operator overloading function is declared as a friend function of the class, so that it can access the private members of the class to operate on it . The left operand of the "<<" operator is a reference of the operator type, ostream is a base class of the cout type, and the right operand is a reference of the Complex type, so that when cout<<c1 is executed, operator<<( cout, c1). This function returns the ostream object passed in through the first parameter as a reference, in order to support continuous output in the form of "cout<<c1<<c2", because the left operand of the second "<<" operator is the return result of the first "<<" operator.

[Summary]
When using the overloading method of non-member functions:

(1) The first operand of the operator to be overloaded is not a type that can be changed. For example, the type of the first operand of the "<<" operator in the above example is ostream, which is the type of the standard library and cannot Like adding member functions to it.

(2) Overloading in the form of non-member functions supports more flexible type conversion. For example, in the above code, 5.0+c1 can be used directly, because the constructor of Complex allows real numbers to be implicitly converted to the Complex type. In this way, 5.0+c1 will be operator+(Complex(5.0),c1)executed in the same way as c1+5.0, which supports the addition of real numbers and complex numbers, which is convenient and intuitive; when overloading with member functions, the left operand must have the Complex type and cannot is a real number, because the target object of calling a member function will not be implicitly converted, and only the right operand can be a real number, because some operands are formal parameters of the function, which can be implicitly converted.

Guess you like

Origin blog.csdn.net/NuYoaH502329/article/details/132162799