[Function overloading and operator overloading: plus, increment, assignment, relational and function call operator overloading]

Article directory

  • Knowledge points of function overloading
    • Overview of function overloading:
  • operator overloading
    • plus operator overloading
    • Increment operator overloading
    • assignment operator overloading
    • relational operator overloading
    • function call operator overloading
  • Experimental results of operator overloading
    • The return value of a function cannot be used as a condition for function overloading
    • References as conditions for function overloading
    • Function overloading encounters default parameters
    • Addition operator – use member function to overload the addition operator
    • Addition operator – Overloading the addition operator using global functions
    • Overloading of left shift operator
    • Increment operator overloading
    • Overloading of assignment operator
    • Overloading of relational operators
    • overloading of the function call operator

Knowledge points of function overloading

Overview of function overloading:

Function: the function name can be the same, improving reusability
Function overloading satisfies the conditions:

  • under the same scope
  • same function name
  • Function parameter types are different, or the numbers are different or the order is different

Note: The return value of a function cannot be used as a condition for function overloading

#include <iostream>
using namespace std;
void fun()
{
cout << "this is a func" << endl;
}
void fun(int a)
{
cout << "this is a func(int a)" << endl;
}
int main()
{
fun(10);
fun();
system("pause");
return 0;
}

//Precautions:
//The return value of the function cannot be used as a condition for function overloading, which will be ambiguous

1. Precautions for function overloading

  • References as overloaded conditions
#include <iostream>
using namespace std;
void fun(int & a)
{
cout << "this is a func(int & amp; a)" << endl;
}
void fun(const int & a)
{
cout << "this is a func(const int & amp; a)" << endl;
}
int main()
{
fun(10);
int a = 10;
fun(a);
system("pause");
return 0;
}


  • Function overloading encounters default parameters

Because there are default parameters, when the function is called, it can be called without writing some parameters, which will cause the two functions to be ambiguous, try to avoid

#include <iostream>
using namespace std;
void fun(int a)
{
cout << "this is a func(int a)" << endl;
}
void fun(int a, int b = 10)
{
cout << "this is a func(int a,int b)" << endl;
}
int main()
{
fun(10, 20);
//fun(10); Both functions can be called, resulting in ambiguity
system("pause");
return 0;
}

Operator overloading

Operator overloading concept: redefine existing operators and give them another function to adapt to different data types

Plus operator overloading

Function: realize the operation of adding two custom data types

Overloading the plus operator with member functions

#include <iostream>
using namespace std;
class Person {
public:
int m_A;
int m_B;
Person operator + (Person & p) {
Person temp;
temp.m_A = this->m_A + p.m_A;
temp.m_B = this->m_B + p.m_B;
return temp;
}

};

void text01() {
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
Person p3 = p1 + p2;
cout << p3.m_A << endl;
cout << p3.m_B << endl;
}
int main()
{
text01();
system("pause");
return 0;
}


Overloading the plus operator with a global function

#include <iostream>
using namespace std;
class Person {
public:
int m_A;
int m_B;

};

Person operator + (Person & amp; p1, Person & amp; p2)
{
Person temp;
temp.m_A = p1.m_A + p2.m_A;
temp.m_B = p1.m_A + p2.m_B;
return temp;
}

void text01() {
Person p1;
p1.m_A = 10;
p1.m_B = 10;
Person p2;
p2.m_A = 10;
p2.m_B = 10;
Person p3 = p1 + p2;
cout << p3.m_A << endl;
cout << p3.m_B << endl;
}
int main()
{
text01();
system("pause");
return 0;
}
2. Left shift operator overloading
#include <iostream>
using namespace std;

class Person {
public:
int m_A;
int m_B;
};


//ostream object can only be used by one, and only global functions can be used
ostream & amp; operator<<(ostream & amp; cout, Person & amp; p) {
cout << "m_A=" << p.m_A << " m_B= " << p.m_B;
return cout;
}

void text02()
{
Person p;
p.m_A = 10;
p.m_B = 10;

cout << p << endl;
}
int main()
{
text02();
system("pause");
return 0;
}

Summary: Overloading the left shift operator with friends can output custom data types

Increment operator overloading

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;

class Integer
{
//friend ostream & amp; operator<< (ostream & amp; cout, const Integer & amp; temp);
public:
Integer() {}

// Pre-increment operator overloading:
Integer & operator ++ ()
{
this->integer ++ ;
return *this;
}

// Post-increment operator overloading:
//Pay attention to the return value, not a reference
Integer operator + + (int)
{
Integer temp = *this;
this->integer ++ ;
return temp;
}

//It is not a constant function, because the object passed in is const modified, so the formal parameter must also be const modified
//The first formal parameter is the compiler's default this pointer, which cannot be written explicitly, so add a const after the parentheses to indicate that the modified this pointer
void display() const
{
cout <<this->integer;
}

protected:
private:
int integer{};
};

ostream & amp; operator<< (ostream & amp; cout, const Integer & amp; temp)
{
//cout << "integer = " << temp.integer << endl;
temp. display();
return cout;
}

//The output object is a class, which needs to overload the operator<<
//ostream & amp; operator<< (ostream & amp; cout, const Integer & amp; temp)
//{
// cout << "integer = " << temp.integer << endl;
//}

void test01()
{
Integer pinteger01;
+ + pinteger01;
cout << ( + + pinteger01 ) << endl;
cout << pinteger01 << endl;
}

void test02()
{
Integer pinteger02;
pinteger02++;
cout << pinteger02 + + << endl;
cout << pinteger02 << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}

// first call:
//Call the copy function -> the integer value of the original class + 1 -> return an object of the copied class
//Second call:
//Call the copy function (the integer value of the copied class has been self-incremented on the original basis) -> the integer value of the original class + 1 -> return an object of the copied class

Assignment operator overloading

#include <iostream>
#include<string>
using namespace std;

class People
{
public:
    People(string name = "", int* ptr = NULL); // normal constructor,
    People(const People & amp; peo); //display declaration copy constructor
    ~People();
    void Display();
    void SetAge(int age);
private:
    string m_name;
    int* mp_age;

};


People::People(string name, int* ptr)
{
    m_name = name;
    mp_age = ptr;
}

People::People(const People & peo)
{
    this->m_name = peo.m_name;
    this->mp_age = new int(*peo.mp_age); //reapply for a piece of memory to store age, to avoid two objects using the same piece of memory
}

People::~People()
{
    delete mp_age; // freeing memory multiple times without overloading the assignment operator will cause a crash.
    mp_age = NULL;
}


void People::Display()
{
    cout << m_name << " is age " << *mp_age << endl;
}

void People::SetAge(int age)
{
    *mp_age = age;
}

int main()
{
    int* ptr = new int(10);
    string name = "Xiao Ming";
    People people1 = People(name, ptr);
    People people2;
    people2 = people1; //Do not overload the assignment operator

    people1. Display();
    people2. Display();

    people1.SetAge(15); // modify people1 age

    people1. Display();
    people2. Display();

    system("pause");

    return 0;
}


Relational operator overloading

#include<iostream>
using namespace std;
#include<string>

// Overloading relational operators

class Person
{
public:
Person(string name, int age)
{
m_name = name;
m_age = age;
}

//Overload == number
bool operator==(Person & p)
{
if (this->m_name == p.m_name & amp; & amp; this->m_age == p.m_age)
return true;
return false;
}

bool operator!=(Person & p)
{
if (this->m_name != p.m_name || this->m_age != p.m_age)
return true;
return false;
}
string m_name;
int m_age;
};


void test1()
{
Person p1("Tom", 18);
Person p2("Tom", 18);

if (p1 == p2)
{
cout << "p1==p2" << endl;
}
else
{
cout << "p1 and p2 are not equal!" << endl;
}
if (p1 != p2)
{
cout << "p1!=p2" << endl;
}
else
{
cout << "p1 and p2 are equal!" << endl;
}
}


int main()
{
test1();

system("pause");
return 0;
}

Function call operator overloading

#include <iostream>
#include <string>
using namespace std;
// function call operator overloading

//Print output class
class MyPrint
{
public:
// overloaded function call operator
void operator()(string test)
{
cout << test << endl;
}
};
void MyPrint02(string test)
{
cout << test << endl;
}
void test01()
{
MyPrint myPrint;
myPrint("hello world");//Because it is very similar to a function call, it is called a functor
MyPrint02("hello world");
}
//The functor is very flexible, there is no fixed way of writing
//addition class
class MyAdd
{
public:
int operator()(int num1, int num2)
{
return num1 + num2;
}

};
void test02()
{
MyAdd myadd;
int ret = myadd(100, 100);
cout << "ret=" << ret << endl;

// anonymous function object
cout << MyAdd()(100, 100) << endl;
}
int main()
{
test01();
test02();
system("pause");
return 0;
}


Experimental results of operator overloading

The return value of a function cannot be used as a condition for function overload

References as conditions for function overloading

Function overloading encounters default parameters

Addition operator – use member function to overload the addition operator

Addition operator – use global function to overload the addition operator

Overloading of left shift operator

Increment operator overload

Overloading of assignment operator

Overloading of relational operators

Overloading of the function call operator

Summary: Through this experiment, I have basically mastered the method of realizing polymorphism through operator overloading, learned the member function method and friend function method of operator overloading, and can basically distinguish the preposition and postposition of unary operators. Operator overloading is to give multiple meanings to existing operators, so that different types of data in the scope of an operator will lead to different behaviors. C++ provides a method for operator overloading, that is, operator overloading functions. The name of the function specifies The operator is followed by an overloaded operator. The overloaded operator function can make a new interpretation of the operator, that is, it can define various operations required by the user, but after the operator is overloaded, the original basic semantics remain unchanged, the priority of the operator is not changed, and the operation is not changed The associativity of the operator does not change the operands required by the operator, and cannot create a new operator. The priority and associativity are mainly reflected in the use of overloaded operators, and the number of operands is not only reflected in the overloading The use of operators is more related to the parameter setting when the function is defined. The functions of operators cannot directly operate on them, so we need to overload the operators. The actual meaning is to give operators new functions, so that they can operate on the classes and structures defined by ourselves. You can see the superiority of C++ through operator overloading, but because your foundation is not good enough, you should exercise more to become more familiar with C++.