In depth parsing of operator overloading in C++ programming

  • 2020-05-09 18:59:01
  • OfStack

The predefined operators in C++ can only operate on primitive data types; in fact, similar operations are required for many user-defined types. Such as:


class complex 
{ 
 public: 
 complex(double r=0.0,double I=0.0){real=r;imag=I;} 
 void display(); 
 private: 
 double real; 
 double imag; 
}; 
complex a(10,20),b(5,8); 

How to implement the "a+b" operation? At this point, we need to write our own program to explain what "+" should do when acting on complex class objects. This is called operator overloading. Operator overloading is to assign multiple meanings to existing operators so that the same operator ACTS on different types of data resulting in different types of behavior.
The essence of operator overloading is function overloading. In the implementation process, first of all, the specified operator expression into the operator function call, operator object into operator function argument, and then according to the type of argument to determine the need to call the standard function, this process is completed in the compilation process.

1. Rules for operator overloading
Operator overloading rules are as follows:
All but a few of the operators in C++ can be overridden, and only the existing operators in C++ can be overridden.
The priority and associativity of the operator will not change after overloading.
(3) operator overloading is an appropriate transformation of the original operator for the actual needs of the new type of data. In general, the function of overloading should be similar to the original function, and the number of operation objects of the original operator cannot be changed, and at least one operation object should be of a custom type.
There are only five operators that cannot be overloaded: the member operator ". ", the pointer operator "*", the scope operator ": :", "sizeof", and the conditional operator "? : ".
There are two types of operator overloading: overloading a member function of a class and overloading a friend function of a class.
Operator overloading a member function of a class as follows:


 Function types  operator  Operator (formal parameter table)  
{ 
  The body of the function.  
} 

Operator overload to the class of friend function 1 syntax is:


friend  Function types  operator  Operator (formal parameter table)  
{ 
  The body of the function.  
} 

Among them, the function type is the operation result type; operator is the keyword that defines the operator overload function. The operator is the name of the overloaded operator.
When the operator is overloaded as a member function of the class, the number of parameters of the function is 1 less than the original number of operations. When overloaded as a friend function of a class, the number of arguments is the same as the original operand. The reason is that when an object is overloaded as a member function of a class, if it USES an overloaded member function, its data can be directly accessed, so it does not need to be passed in the parameter table. The missing operands are the object itself. When overloaded as a friend function, the operation of the friend function on the data of an object must be carried out by the name of the object, so the parameters used should be passed, and the number of operands will not change.
The main advantage of operator overloading is that it allows you to change the way operators used within the system operate to accommodate similar operations of user-defined types.

2. Operator overload as a member function
For the binocular operator B, if you want to overload B as a member function of class so that it can realize the expression oprd1 B oprd2, where oprd1 is an object of class A, you should overload B as a member function of class A. This function has only one formal parameter, and the formal parameter type is the type to which oprd2 belongs. After overloading, the expression oprd1 B oprd2 is equivalent to the function calling oprd1.operator B(oprd2).
For the leading monomial operator U, such as "-" (minus sign), if we want to overload U as a member function of class to realize the expression U oprd, where oprd is an object of class A, then U should be overloaded as a member function of class A, and the function has no formal parameters. After overloading, the expression U oprd is equivalent to the function calling oprd.operator U().
For the post operators "++" and "-", if they are to be overloaded as member functions of the class to implement the expressions oprd++ or oprd--, where oprd is the object of A class, then the operator should be overloaded as a member function of A class, in which case, the function should have an integer parameter. After overloading, the expressions oprd++ and oprd -- just like when the function calls oprd.operator ++(0) and oprd.operator -- (0);
Operator overloading is the giving of multiple meanings to an existing operator. The extensibility of the C++ language is enhanced by redefining the operator so that it can perform specific functions on class-specific objects.
 
1. Function of operator overloading:
Operator overloading allows the operator C/C++ to have one user-defined meaning on a user-defined type (class). Overloaded operators are syntax modifiers for function calls:


class Fred
{
public:
// ...
};
 
#if 0
//  No operator overloading: 
Fred add(Fred, Fred);
Fred mul(Fred, Fred);
 
Fred f(Fred a, Fred b, Fred c)
{
return add(add(mul(a,b), mul(b,c)), mul(c,a)); //  Haha, how ridiculous ...
}
#else
//  Operator overloading: 
Fred operator+ (Fred, Fred);
Fred operator* (Fred, Fred);
 
Fred f(Fred a, Fred b, Fred c)
{
return a*b + b*c + c*a;
}
#endif

 
2. Operators that can be used as overloads:
Arithmetic operator: +,-,*,/,%,++,--;
Bit operator: &,|,~,^, < <, >, >
Logical operator:! , &&, | |.
Comparison operators: <, >, > =, < =,==,! =;
Assignment operator: =,+=,-=,*=,/=,%=,&=,|=,^=, < < =, > > =;
Other operators: [], (), - >, (comma operator), new, delete, new [], delete [], - > *.
The following operators are not allowed to be overloaded:
.,.*,::,?:
 
3. Priority and associativity after operator overload:
The user overloads the new defined operator without changing the priority and associativity of the original operator. That is, operator overloading does not change the precedence or associability of the operator, and it does not change the syntactic structure of the operator when the operator is overloaded, that is, the unary operator can only be overloaded as a unary operator, and the binocular operator can only be overloaded as a binocular operator.
 
4. How the compiler chooses which operator function:
Operator overloading is actually one function, so operator overloading is actually an overloading of the function. The compiler's choice of operator overload follows the principle of function overload. When a less obvious operation is encountered, the compiler looks for an operator function whose parameters match.
 
5. What are the limitations of overloaded operators:
(1) no new operator can be invented. Overloaded operators must be limited to operators that allow overloading within the range of existing operators in the C++ language.
(2) the overload operator insists on four "cannot be changed".
· cannot change the number of operator operands;
· the original priority of the operator cannot be changed;
· the original associativity of the operator cannot be changed;
· cannot change the original syntactic structure of the operator.
 
6. What principles must be followed when operator overloading:
Operator overloading can make programs more concise, make expressions more intuitive, and increase readability. However, operator overloading should not be used too much, otherwise it will cause 1 definite trouble.
(1) the meaning of overload operator must be clear.
(2) overloaded operator cannot have 2 meanings.
Operator overload function in two forms
Operator-overloaded functions take the following two forms: the member function form and the friend function form. Both forms allow access to private members of a class.

Example 3.
Use global function overloading


#include <IOSTREAM.H> 
 
class A 
{ 
public: 
  A(int i):i(i){}; 
  void print(){cout<<i<<endl;} 
  friend A operator + (A &a, A &b);// Declare them as friends  
  friend A operator ++(A &a, int); 
  friend A& operator ++(A &a); 
  friend A& operator +=(A &a, A &b); 
protected: 
  int i; 
private: 
}; 
 
A operator + (A &a, A &b){// overloading  a + b 
  return A(a.i + b.i); 
} 
 
A operator ++(A &a, int){// overloading  a++ 
  return A(a.i++); 
} 
 
A& operator ++(A &a){// overloading  ++a 
  a.i++; 
  return a; 
} 
 
A& operator +=(A &a, A &b){// overloading  += 
  a.i += b.i; 
  return a; 
} 
 
void main(){ 
  A a(5); 
  A b(3); 
  (a += b).print(); 
} 

 
Use a member function overload


#include <IOSTREAM.H> 
 
class A 
{ 
public: 
  A(int i):i(i){}; 
  void print(){cout<<i<<endl;} 
  A operator + (A &b); 
  A& operator += (A &b); 
  A operator ++(int); 
  A& operator ++(); 
protected: 
  int i; 
private: 
}; 
 
A A::operator + (A &b){// overloading  + 
  return A(i + b.i); 
} 
 
A& A::operator+= (A &b){ 
  i += b.i; 
  return *this; 
} 
 
A A::operator++ (int){//i++ 
  return A(i++); 
} 
 
A& A::operator ++(){//++i 
  i++; 
  return *this; 
} 
 
void main(){ 
  A a = 2; 
  A b = 3; 
  (++a).print(); 
  (b++).print(); 
} 


Related articles: