Classes and Objects Intermediate (C++)

At the end of the last article, we talked about the this pointer. This time, starting from the empty class, all the content of this article will revolve around the empty class. …

Introduction:

1. The 6 default member functions of the class

2. Constructor

3. Destructor

4. Copy constructor

5. Operator overloading

6. const member function

7. Address and const address operator overloading

content

1. The 6 default member functions of the class

2. Constructor

1. What is a constructor:

2. Function:

3. Default constructor:

4. Features:

3. Destructor

1. What is a destructor?

2. Function:

3. Default destructor:

4. Features:

4. Copy constructor

1. What is a copy constructor?

2. Function:

3. What is a shallow copy?

4. Features:

5. Why does it cause infinite recursive calls when passing parameters to the copy constructor by value?

6. Since the default copy constructor generated by the compiler can already complete the byte order value copy, do we still need to implement it ourselves?

7. Scenarios that use the copy constructor:

5. Assignment operator overloading

1. Why use operator overloading?

2. Function name and function prototype

 3. Precautions

 4. Assignment operator overloading

6. const member function

1. What is a const member function?

2. Can a const object call a non-const member function?

3. Can non-const objects call const member functions?

4. Can other non-const member functions be called within a const member function?

5. Can other const member functions be called from within a non-const member function?

Seven. Address operator overloading and const address operator overloading

1. Note:

2. Take the address: 

3. const takes the address:


1. The 6 default member functions of the class

If there are no members in a class, referred to as an empty class for short, then there is nothing in the empty class? It is not nothing, any class will automatically generate the following 6 default member functions if we do not write it.

So what is the default member function? ----> The user does not write it, the compiler will automatically generate it, but if the user shows the definition, the compiler will no longer generate it.

2. Constructor

1. What is a constructor:

The constructor is a special member function with the same name as the class name. It is automatically called by the compiler when an object of a class type is created to ensure that each data member has an appropriate initial value, and is only called during the entire life cycle of the object. once.

2. Function:

Initialize the object, ensuring that each data member in the object has an appropriate initial value.

3. Default constructor:

The default constructor automatically generated by the compiler can only assign random values ​​to the member variables in the object when the object is initialized, and if there is scheduling of space resources in our object, we must define our own constructor instead of using the default constructor. function.

4. Features:

1. The function name is the same as the class name.

2. No return value.

eg:

class Date{
    Date(){
        //该函数就是一个默认的构造函数.        
    }
}

3. When the object is instantiated, the compiler automatically calls the corresponding constructor.

Notice:

①. If we pass parameters when creating an object, the compiler will call the corresponding constructor according to the parameters to initialize the object.

②. If we create the object directly and do nothing, the compiler will automatically call the default constructor to complete the initialization of the object, so what is the default constructor? There are the following three.

        a. We do not show the definition, the default constructor generated by the system itself.

        b. We explicitly define the parameterless constructor.

        c. We explicitly define the full default constructor.

4. Constructors can be overloaded

think:

a. Because the constructor can be overloaded, we can initialize the object according to our own requirements. Without this feature, we can only use the default constructor, which may affect our programming efficiency.

Notice:

a. If an object is created by a parameterless constructor, the object does not need to be followed by parentheses, otherwise it becomes a function declaration. For example: Date d3(); This code declares the d3 function, which has no parameters, the function name is d3, and returns The value is a date type.

eg:

class Date{
 
public :
 // 1.无参构造函数
 Date ()
 {}
 
 // 2.带参构造函数
 Date (int year, int month , int day ){
     _year = year ;
     _month = month ;
     _day = day ;
 }

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

void TestDate(){
     Date d1; // 调用无参构造函数
     Date d2 (2015, 1, 1); // 调用带参的构造函数 
}

5. If the user does not write it himself, the compiler will automatically generate a default constructor with no parameters, but if the user shows the definition, the compiler will no longer generate it.

Notice:

a. The explicit definition we are talking about here has nothing to do with the above overload. The explicit definition here refers to the case of defining a parameterless default constructor or a full default default constructor, the compiler will no longer generate it, but If we explicitly define a constructor that requires us to specify parameters in the form of overloading, then this constructor does not belong to the default constructor, and the compiler will still automatically generate a default constructor with no parameters.

6. No-parameter constructors and all-default constructors are called default constructors, and there can only be one default constructor, no-parameter constructors, all-default constructors, and compiler-generated default constructors, here The default means that the compiler calls the constructor by default when the object is created.

Thought: Are the default constructors automatically generated by the compiler useful?

a. Assuming that the member variables in our class are all system types, after the default constructor generated by the compiler is called, the initial value of the member variables is still random, and the default constructor is not useful at this time.

b. Assuming that the member variables in our class not only have system-type variables, but also objects of our custom type (which also belong to member variables), then how do we implement the member variables of his internal custom type when we instantiate the class For initialization, we cannot initialize it directly. At this time, the compiler will play a role when it calls the automatically generated default constructor. The compiler calls the default constructor corresponding to the internal custom member variable in the generated default constructor. Complete the initialization of custom member variables in the class.

eg:

class Time{
public:
   Time(){
       cout << "Time()" << endl;
       _hour = 0;
       _minute = 0;
       _second = 0;
   }
private:
  int _hour;
  int _minute;
  int _second;
};

class Date{
private:
  // 基本类型(内置类型)
  int _year;
  int _month;
  int _day;
  // 自定义类型
  Time _t;
};

int main(){
//在创建对象d时我们不能直接完成对_t的初始化,此时Date中编译器自动生成的默认构造函数产生作用
//创建对象d时,会自动调用Date中默认的构造函数,而默认的构造函数会调用_t这个自定义对象的构造函数
//完成对_t的初始化
   Date d;
   return 0;
}

3. Destructor

1. What is a destructor?

Contrary to the function of the constructor, the destructor does not complete the destruction of the object itself, the local object destruction is completed by the compiler, and the object will automatically call the destructor when it is destroyed to complete the cleanup of resources in the object.

2. Function:

Complete the cleanup of resources in the object. (Resources in the object ---> memory space applied for on the heap, file pointers, sockets....)

3. Default destructor:

A class has one and only one destructor. If it is not explicitly defined, the system will automatically generate a default destructor. However, in order to clean up the resources in the object, we must define the destructor ourselves. The compiler defaults to the destructor. The generated destructor does not have this capability.

4. Features:

1. The destructor name is preceded by the character ~.

2. No parameter and no return value.

eg:

class Date{
    ~Date(){
        //该函数就是一个默认的析构函数.        
    }
}

3. A class has one and only one destructor. If it is not explicitly defined, the system will automatically generate a default destructor.

Notice:

Destructors do not have overloading characteristics. A class has only one destructor. If we explicitly define it, the compiler will not generate it automatically. If there are space resources in our object that we need to release, we must define the destructor ourselves. When defining a function, it should be noted that the function name is prefixed with ~ before the class name, there is no return value, no parameters, and the operation of releasing resources can be placed in the function body.

4. At the end of the object life cycle, the C++ compilation system automatically calls the destructor.

Thinking: The destructor generated by default cannot release space resources. Objects without space resources can end naturally when they are destroyed, and there is no need to perform related destruction work. So what is the use of the default destructor?

a. If the member variables in our class do not have a custom type, then the destructor generated by the compiler by default has no effect.

b. If there are some member variables of custom type in our class, these variables cannot be directly released when the object is destroyed, then the default destructor generated by the compiler at this time will call it on the members of the custom type destructor of .

eg:

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;
};


class Person{
private:
  String _name;//自定义类型
  int _age;
};


int main(){
//当我们的对象p生命周期结束时,需要对p对象中的资源进行释放,p对象并没有资源,但是p对象中的自定义
//类型对象_name中有空间资源,我们没法直接对其进行释放,此时p对象中的默认析构函数的作用就体现出
//来了,它会调用自定义类型对象中的析构函数,将该自定义类型对象中的资源释放.
  Person p;
  return 0;
}

4. Copy constructor

1. What is a copy constructor?

There is only a single parameter in this function, which is a reference to an object of this class type (usually modified with const to prevent it from being modified), which is automatically called by the compiler when a new object is created with an existing class type object.

2. Function:

When creating a class type object, you can shallowly copy the value of the existing class type object to the object to be created. (The default copy constructor automatically generated by the compiler can only perform a shallow copy, if you want to complete a deep copy, you need to We define the copy constructor ourselves.)

3. What is a shallow copy?

Shallow copy refers to the copying of byte order values. In other words, the corresponding member variables in objects of the same class type are copied in a one-to-one manner.

4. Features:

1. Copy constructor is an overloaded form of constructor.

How to define:

Date(const Date& d){
    _year = d._year;
    _month = d._month;
    _day = d._day;
}

2. There is only one parameter of the copy constructor, and the parameter must be passed by reference. If the parameter is passed by value, it will cause infinite recursive calls.

3. If there is no explicit definition, the system generates a default copy constructor, and the default copy constructor object completes the copy according to the memory storage and byte order. This copy is called shallow copy, or value copy.

5. Why does it cause infinite recursive calls when passing parameters to the copy constructor by value?

a. First of all, we need to know that we normally pass parameters by reference. Let's see why we don't pass parameters by value.

b. First of all, take a normal function as an example, what happens when we pass parameters in the form of values, the compiler will generate a temporary variable of the same type as the actual parameter after passing the actual parameter of the function to the value of the actual parameter. Copy, and then use this temporary variable in the function, which has nothing to do with the actual parameter. At this time, let's look at what happens when the parameter is passed in the form of value in the copy constructor. First, the function receives the actual parameter object we passed. , but because it is a value-passing parameter, the function will create a temporary object at this time, and copy the value in the actual parameter object to this temporary object, so how to make it complete the copy of an actual object when creating an object? , of course, with the actual parameter object as a parameter, the copy constructor of the temporary object is called. At this time, it is back to the time when the constructor was just called to pass the parameters. This way, the recursive call will continue, so we are copying the constructor. You cannot use pass-by-value when passing parameters.

.​

6. Since the default copy constructor generated by the compiler can already complete the byte order value copy, do we still need to implement it ourselves?

a. When defining a member variable in our class, if the type of the member variable is only an ordinary variable, then we really don't need to define a copy constructor ourselves.

b. If the type of the member variable is a pointer type, an accident will occur. When the copy constructor is called, the contents of the member pointer variable in the existing object will be completely copied to the pointer variable in the newly generated object. At this time The pointer variables in the two objects are stored at the same address, which means they point to the same memory space. At the end of the program, the last object will be destroyed first, and the destructor in the object will destruct the pointer. The space pointed to by the variable is released, and when the previous object is destroyed, after the destructor of the object is called, the space pointed to by the pointer variable will be released again, because the space pointed to by the pointer has been After the release, the pointer variable has also become a wild pointer, and the program will crash if the space it points to is released, so in this case, we need to define our own copy constructor.

7. Scenarios that use the copy constructor:

1. Create a new object using an existing object.

2. When the formal parameter type of the function is an object of class type.

3. When the return value type of the function is an object of class type.

Note:   Therefore, in the above scenarios, we will call the copy constructor, which greatly affects the efficiency of the program. Therefore, in order to improve the efficiency of the program, we should try to use reference types when passing parameters in general objects. When the function returns, according to the actual scene, we can use references as much as possible. .

5. Assignment operator overloading

1. Why use operator overloading?

C++ introduces operator overloading to enhance the readability of the code. Operator overloading is a function with a special function name, and also has a return value type, function name and parameter list. The return value type and parameter list are similar to ordinary functions.

2. Function name and function prototype

eg:

bool operator==(const Date& d1, const Date& d2)//==运算符重载
{
 return d1._year == d2._year;
 && d1._month == d2._month
 && d1._day == d2._day;
}

 3. Precautions

1. You cannot create new operators by connecting other symbols: such as operator@

2. An overloaded operator must have an operand of a class type or an enumeration type.

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. As an overloaded function of a class member, its formal parameters appear to be 1 less than the number of operands, and the operator of the member function has a default parameter this, which is limited to the first parameter.

5. Which operators cannot be overloaded and which ones can.

 4. Assignment operator overloading

a. The assignment operator mainly pays attention to four points:

1. Parameter type 2. Return value 3. Check whether you assign a value to yourself 4. Return *this

b. Note:

1. If a class does not explicitly define an assignment operator overload, the compiler will also generate one to complete the endian value copy of the object (shallow copy).

2. Assignment operator overloading can only be defined in a class. If we define a global assignment operator overloading outside the class, there is no assignment operator overloading in the class, so the compiler will generate a default assignment operator overloading. At this time, this The default assignment operator overload is duplicated with the global assignment operator overload outside the class, which will conflict, so the assignment operator overload must be placed in the class.

c. Then the default assignment overload function generated by the compiler can already complete the byte order value copy, do we still need to implement it ourselves?

Needed in specific cases, the specific reason is equivalent to the copy constructor.

6. const member function

1. What is a const member function?

a. The const-modified class member function is called a const member function. The const-modified class member function actually modifies the implicit this pointer of the member function. The const is actually placed at the front of the this pointer, indicating that in the member function No member of the class can be modified.

eg:

2. Can a const object call a non-const member function?

No, const objects can only be accessed, not *this objects in const member functions, which are accessible and modifiable.

3. Can non-const objects call const member functions?

Yes, non-const objects can be accessed and modified, *this in const functions can only be accessed, so yes.

4. Can other non-const member functions be called within a const member function?

No, *this in const functions can only be accessed, while *this in other non-const functions can be accessed and modified.

5. Can other const member functions be called from within a non-const member function?

Yes, *this in non-const functions can be accessed and modified, while *this in const functions can only be accessed.

Seven. Address operator overloading and const address operator overloading

1. Note:

Generally, these two operators do not need to be overloaded. You can use the overload of the default address fetching generated by the compiler. Only in special cases, overloading is required, for example, if you want others to get the specified content.

2. Take the address: 

Take the date class as an example:

Date* operator&(){

   return this ;

}

3. const takes the address:

Take the date class as an example:

const Date* operator&()const{
 
    return this ;
 
}

Guess you like

Origin blog.csdn.net/weixin_49312527/article/details/123636421