C++ assignment operation overloading, const member, address taking and const address taking operator overloading

C++ assignment operation overloading, const member, address taking and const address taking operator overloading

  • 1. Assignment operator overloading
    • 1.1 Operator overloading
    • 1.2 Assignment operator overloading
    • 1.3 Prefix + + /– and postfix + + /– overloading
  • 2. const members
  • 3. Address retrieval and const address retrieval operator overloading

Column: C “Gaga” System Learning
> Blogger homepage: Chuyang 785
>Code hosting: chuyang785
>Thank you all for your support. Your likes and attention are the greatest support for me! ! !
> Bloggers will work harder to create better blog posts! !
>Follow me, follow me, follow me. Say important things three times! ! ! ! ! ! ! !

1. Assignment operator overloading

1.1 Operator overloading

  • We know that suitable operations can be performed between two built-in types. For example, two integers can be added, subtracted, multiplied and divided, and the size relationship between two numbers can also be compared. This corresponds to the char and double types. Similar operations can be performed. But these are only limited to built-in types. What if they become custom types? Can custom types also perform the same operations as custom types? So in order to solve this method, C++ has the concept of operator overloading.

C++ introduces operator overloading in order to enhance the readability of the code. Operator overloading is a function with a special function name and also has its own
The return value type, function name and parameter list are similar to those of ordinary functions.
The function name is: the keyword operator is followed by the operator symbol that needs to be overloaded.
Function prototype: return value type operator (parameter list)

  • Notice:
    1. New operators cannot be created by connecting other symbols: such as operator@
    2. Overloaded operators must have a class type parameter
    3. The meaning of operators used for built-in types cannot be changed. For example: the built-in integer type + cannot change its meaning.
    4. When overloaded as a class member function, its formal parameters appear to be 1 less than the number of operands, because the first parameter of the member function is hidden this
    4..* :: sizeof ?: . Note that the above five operators cannot be overloaded. This often appears in multiple-choice questions in written exams
    now
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// bool operator==(Date* this, const Date & d2)
// What needs to be noted here is that the left operand is this, pointing to the object of the calling function
bool operator==(const Date & amp; d2) //operator
{
return _year == d2._year
& amp; & amp; _month == d2._month
& amp; & amp; _day == d2._day;
}
private:
int _year;
int _month;
int _day;
};

int main()
{
Date d1;
Date d2;

bool ret = d1 == d2; // --> The essence is d1.operato==(d2); (operato== is regarded as a function name as a whole), but after optimization, it can be used directly
if (ret)
{
cout << "d1 == d2" << endl;
}
else
{
cout << "d1 != d2" << endl;
}
return 0;
}

1.2 Assignment operator overloading

1. Assignment operator overloading format

  • Parameter type: const T & amp;, passing a reference can improve the efficiency of parameter passing.
  • Return value type: T & amp;, returning a reference can improve the efficiency of return. The purpose of returning a value is to support continuous assignment
  • Check whether you assign a value to yourself
  • Return *this: To compound the meaning of continuous assignment
class Date
{
public:
Date(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
Date(const Date & d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
Date & operator=(const Date & d)
{
if (this != & amp;d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
return *this;
}
private:
int _year;
int _month;
int _day;
};

int main()
{
Date d1;
Date d2(2023, 10, 28);
d1 = d2;//Essentially--> d1.operator=(d2)

return 0;
}
  1. The assignment operator can only be overloaded as a member function of the class and cannot be overloaded as a global function.
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
int _year;
int _month;
int _day;
};
// The assignment operator is overloaded into a global function. Note that when overloaded into a global function, there is no this pointer and two parameters need to be given.
Date & amp; operator=(Date & amp; left, const Date & amp; right)
{
if ( & amp;left != & amp;right)
{
left._year = right._year;
left._month = right._month;
left._day = right._day;
}
return left;
}

int main()
{
Date d1;
Date d2(2023, 10, 28);
d1 = d2;//Essentially--> d1.operator=(d2)

return 0;
}

We are looking at a piece of code:

class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
int _year;
int _month;
int _day;
};

int main()
{
Date d1;
Date d2(2023, 10, 28);
d1 = d2;//There is no overloading here, but it is also possible

return 0;
}
  • Reason: If the assignment operator is not implemented explicitly, the compiler will generate a default. At this time, the user can implement it himself outside the class.
    A global assignment operator overload conflicts with the default assignment operator overload generated by the compiler in the class, so assignment
    Operator overloading can only be member functions of a class

3. When the user does not implement it explicitly, the compiler will generate a default assignment operator overload and copy it byte by byte in the form of value. Note
Note: Built-in type member variables are directly assigned, while custom type member variables need to call the assignment operator of the corresponding class.
Overloading completes the assignment. This is the same as the previous copy structure.

  • Then some friends will ask, since we don’t write explicit operator overloading and the compiler will help us achieve the overloading effect, then why do we need to write another one ourselves? At this time we can review our previous copy construction. When we are not involved in resource management, the copy construction is normal, but once we malloc a piece of space, there will be a problem, and it is the same here, initial assignment Operation is a special copy construct.

1.3 Prefix + + /– and postfix + + /– overload

class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
// Prepend + +: Return the result after + 1
// Note: The object pointed to by this will not be destroyed after the function ends, so it is returned by reference to improve efficiency.
Date & operator + + ()
{
_day + = 1;
return *this;
}
private:
int _year;
int _month;
int _day;
};
  • The above is the operator overloading operation of preceding ++.
    Now, friends, think about what to do with post + +?
    The first is what is its overloading format?
    What is the return type?
    Because our postfix ++ rule is to use ++ first and then ++ , which means that ++ will only be used after the end of a statement.
    So how do we achieve it?

In order to distinguish prefix and postfix in C++, C++ uses placeholder parameters to distinguish prefix and postfix. Those without placeholder parameters are prefixes, and those with placeholder parameters are postfix, and the occupancy is stipulated. The type of bit parameters is int.

class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
//Postfix + +:
// Prefix + + and postfix + + are both unary operators. In order to make the prefix + + and postfix + + form correctly overloaded
// C++ stipulates: postfix + + adds an extra int type parameter when overloading, but this parameter does not need to be passed when calling the function, the compiler automatically passes it
// Note: Postfix + + is used first and then + 1, so the old value before + 1 needs to be returned. Therefore, you need to save a copy of this first during implementation, and then give this + 1
// Temp is a temporary object, so it can only be returned as a value, not a reference.
Date operator + + (int)
{
Date temp(*this);//Save the original value first
_day + = 1; //Add again
return temp;//Finally return the saved value
}
private:
int _year;
int _month;
int _day;
};

2. const members

The const-modified “member function” is called a const member function. The const-modified class member function actually modifies the member function.
The implicit this pointer indicates that no member of the class can be modified in this member function.

class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}

void Print()
{
cout << _year << "/" << _month << "/" << _day << endl;
}

private:
int _year;
int _month;
int _day;
};

int main()
{
Date d1(2023, 11, 1);
d1.Print();
return 0;
}

We see that there is nothing wrong with this string of code, but what if I modify d1 with const?

const Date d1(2023, 11, 1);
d1.Print();

Can it still pass at this time?

An error will be reported at this time because there is permission amplification:
Originally:

  • But when we modify d1 with const, the type we pass is const and d1 cannot be modified, but the parameter type accepted by our function is not a const unmodifiable type, so there is a problem of permission amplification.
    The solution to this problem is also very simple, which is to change our formal parameters to const modified parameters: that is, const Date* const this
    But the problem is that const is added there. C++ stipulates that member functions should be added after the formal parameter list with const modification:

Let’s take a look at this code:

class Date
{
public:
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}

void Print() const
{
cout << _year << "/" << _month << "/" << _day << endl;
}

private:
int _year;
int _month;
int _day;
};

int main()
{
const Date d1(2023, 11, 1);
d1.Print();

Date d2(2023, 11, 1);
d2.Print();
return 0;
}
  • Will d2 here be wrong?
    Analysis, our member function is decorated with const, but d2 is not decorated with const.
    But no error will be reported here, because this is a reduction of permissions.
    C++ provides that permissions allow for panning and narrowing of permissions.
    So since the permissions are allowed to be reduced, it is recommended that when writing member functions, the member objects cannot be modified and should be modified with const as much as possible. This can better ensure the fault tolerance rate of the code, because even if the member objects are not modified with const, the permissions can be reduced. This feature is still passable.

3. Address retrieval and const address retrieval operator overloading

  • These two default member functions generally do not need to be redefined, and the compiler will generate them by default.
class Date
{
public:
Date* operator &()
{
return this;
}
const Date* operator &()const
{
return this;
}
private:
int _year; // year
int _month; // month
int _day; // day
};

int main()
{
Date d1;
Date d2;

cout << & amp;d1 << endl;
cout << & amp;d2 << endl;
return 0;
}