C + + classes and objects (medium)
preface
Continue to learn C + + classes and objects today
Class
1. Constructor
class Date { public: Date() { _year = 0; _month = 0; _day = 0; } private: int _year; int _month; int _day; }; void main() { Date d1; }
Concept:
The constructor is a special member function with the same name as the class name. It is automatically called by the compiler when creating a class type object to ensure that each data member has an appropriate initial value and is called only once in the life cycle of the object
How many points are there in the above paragraph, First, the same function as the class name is the constructor. It is mainly used to initialize the object when we instantiate it, so that the object has an initial value we want, and will only be called automatically when instantiating the object, and only once. After initialization, the object instance will not be called again.
characteristic:
1. The function name is the same as the class name
2. No return value
3. Automatically called when instantiating an object
4. The constructor can be overloaded
5. When we do not explicitly define a constructor, the compiler will automatically generate a default parameterless constructor. If we show that a constructor is defined, the compiler will not generate the default parameterless constructor
6. The default constructor can only have one
7. The compiler will automatically call the constructor of the custom type
2. Destructor
class Date { public: Date() { _year = 0; _month = 0; _day = 0; } ~Date() {} private: int _year; int _month; int _day; }; void main() { Date d1; }
Concept:
At the end of the object's life cycle, the compiler automatically calls the destructor to free up the object space and complete the resource cleaning
characteristic:
1. Add a "~" before the function name is the constructor
2. No parameter, no return value
3. A class has only one destructor. If there is no explicit definition, the compiler will automatically generate a default destructor
4. At the end of the object life cycle, the compiler automatically calls the destructor
5. The compiler will automatically call the destructor of the custom type
3. Copy constructor
class Date { public: Date() { _year = 0; _month = 0; _day = 0; } Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } ~Date() {} private: int _year; int _month; int _day; }; void main() { Date d1; Date d2 = d1; Date d2(d1); }
Concept:
It is the same as the constructor name, but there will be a reference to the class type. Because we copy the construct, we usually use const to modify it.
characteristic:
1. Copy constructor is an overload of constructor
2. The copy constructor has only one parameter and must pass the parameter by reference. Passing the parameter by value will cause infinite recursion
Explanation of infinite recursion:
After the copy structure is defined, when we pass the value, it is equivalent to building a formal parameter object d, but when we build d, because we are using one object to build another object, we will call the copy structure. In this way, infinite recursion occurs. So why can we reference the parameter? Because reference is only an alias of my current object, d1 is given another name d, so there is no need to build a formal parameter object, and then assign the value of d, that is, d1, to the copy object d2 to implement the copy constructor.
3. If there is no explicit definition, the system will automatically generate a default copy constructor, but the default copy constructor only copies according to the byte order of memory storage. This kind of copy is called shallow copy or value copy
4. When the default copy constructor generated by the compiler can complete the value copy, we don't have to rewrite the copy constructor. However, if we still use the default copy function for the string class, we will find a problem. The value of the copied object and the member variable of the copied object are the same address and the same value, Did not open up new space
class String { public: String(const char* str = "jack") { _str = (char*)malloc(strlen(str) + 1); strcpy(_str, str); } ~String() { cout << "~String()" << endl; free(_str); } private: char* _str; }; void main() { String s1("hello"); String s2(s1); }
After the program runs, you will find that the program crashes, so why does it crash? As mentioned above, because it just copies the memory address and does not reopen space, resulting in a space being released twice in a row, so we will see the program crash.
4. Overload of assignment operator
Concept:
In order to enhance the readability of the code, C + + introduces operator overloading. Operator overloading is a function with special function name, and also has its return value type, function name and parameter list. Its return value type and parameter list are similar to 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 [operator] (parameter list)
characteristic:
1. Parameter type
2. Return value
3. Check whether you assign values to yourself
4. Return to * this
5. If a class does not explicitly define the overload of assignment operator, the compiler will also generate one to copy the value of the object in byte order.
The assignment operator is a binocular operator. We need to connect operands to implement it. Please see the following code.
class Date { public: Date() { _year = 0; _month = 0; _day = 0; } Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } Date operator = (const Date& d) { _year = d._year; _month = d._month; _day = d._day; return *this; } ~Date() {} private: int _year; int _month; int _day; }; void main() { Date d1; Date d2 = d1; Date d2(d1); Date d3; d3 = d2 = d1; }
The assignment operator overload mentioned above may be the return value type and return value, as well as the number of parameters.
Return value type - why is it a class name? This depends on how we usually use "=" Let's explain that x = m, which everyone can think of, but sometimes we will wait, for example, x = m = k, because we all know that the operation is from right to left. If so, we set no return value, then what do we use to assign value to X after m = k? Therefore, we need to return a value to assign a value to it. Why is the class name? Because we often use assignment between objects. Its function is similar to copy construction, but we need to instantiate the object in advance, such as d3 above.
Let's talk about the return value and the number of parameters together
In the last article, we mentioned this pointer. We know that non static member functions in the class have a hidden this pointer, that is:
Date operator = (Date* const this,const Date& d) { this->_year = d._year; this->_month = d._month; this->_day = d._day; return *this; }
This is what the function actually looks like. The hidden this is D2 and D3. When calling the overload of the assignment operator, this points to them (left operands) and completes their assignment. Another parameter is the operands, that is, D1 and D2.
Why is the return value * this? Because our this pointer points to the left operand, it stores the address instead of the left operand object, so we need to dereference it and return it. At this time, its type is Date.
5.const member function
The class member function modified by const is called const member function. Const modifies the class member function and actually modifies the implicit this pointer of the member function, indicating that no member of the class can be modified in the member function.
class Date { public: Date() { _year = 0; _month = 0; _day = 0; } Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } Date operator = (const Date& d) { _year = d._year; _month = d._month; _day = d._day; return *this; } void Show_Date() { cout<<" Show_Date()"<<endl; cout<<_year<<" - "<<_month<<" - "<<_day<<" - "<< endl; } void Show_Date()const { cout<<" Show_Date() const"<<endl; cout<<_year<<" - "<<_month<<" - "<<_day<<" - "<< endl; } ~Date() {} private: int _year; int _month; int _day; }; void main() { Date d1; Date d2 = d1; Date d2(d1); Date d3; const Date d4; d3 = d2 = d1; d1.Show_Date(); d4.Show_Date(); }
If we give Show_Date() plus const, what happens? What are the call results of d1 and d4?
void Show_Date(const Date* const this)const { cout<<" Show_Date() const"<<endl; cout<<_year<<" - "<<_month<<" - "<<_day<<" - "<< endl; }
const here is used to modify this pointer, so if we face it here_ year,_ month,_ If it is modified on day, it cannot be modified.
After running, we can know that constant objects call constant numbers, and ordinary objects call ordinary functions.
Here we add:
Const objects cannot call non const member functions
Non const objects can call const member functions
Other non const member functions cannot be called in const member functions
Other const member functions can be called in non const member functions
6. Overload of address fetching and const address fetching operators
class Date { public: Date() { _year = 0; _month = 0; _day = 0; } Date(const Date& d) { _year = d._year; _month = d._month; _day = d._day; } Date operator = (const Date& d) { _year = d._year; _month = d._month; _day = d._day; return *this; } Date* operator&() { return this ; } const Date* operator&()const { return this ; } ~Date() {} private: int _year; int _month; int _day; }; void main() { Date d1; Date d2 = d1; Date d2(d1); Date d3; d3 = d2 = d1; }
Generally speaking, we do not need to overload these two. Unless there are some special requirements, we will directly use the default address fetching character and const address fetching character.
summary
The content of today's study is not only a part of the main functions in the class, but also the member functions existing in each class. It is six member functions that we need to master skillfully and handy. I hope these things we sorted out can be used as a reference for everyone.