Nearly 10,000 words of ultra-detailed C++ classes and objects, come in and have a look

Summary of previous situation:
http://t.csdn.cn/Kqf6D

Table of contents

1. The 6 default member functions of the class

1.1 Constructor

1.1.1 Features:

Its characteristics are as follows:

1.2 Destructor

1.2.1 Features:

Destructors are special member functions that

1.3 copy constructor

1.3.1 Concept:

1.3.2 Features: The copy constructor is also a special member function

1.3.3 Features are as follows:

1.4 Assignment operator overloading

1.4.1 The concept of operator overloading

1.4.2 Assignment operator overloading:

1. Assignment operator overload format

2. The assignment operator can only be overloaded as a member function of a class and cannot be overloaded as a global function

3. When the user does not explicitly implement

1.4.3 Pre-++ and post-++ overloading

1.5 const members

​edit

1.6 Address and const address operator overloading

2. Initialization list

3. static members

3.1 Concept:

3.2 Features

4. Inner classes

characteristic:

5. Some compiler optimizations when copying objects

5.1 Summary of Object Returns

5.2 Summary of function parameter passing

6. Anonymous objects


1. The 6 default member functions of the class

If there are no members in a class, it is simply called an empty class. When nothing is written in any class, the compiler will automatically generate the following 6 default member functions.

Default member function: The member function generated by the compiler without explicit implementation by the user is called the default member function.

1.1 Constructor

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

1.1.1 Features:

The constructor is a special member function. It should be noted that although the name of the constructor is called construction, the main task of the constructor is not to open space to create objects, but to initialize objects.

Its characteristics are as follows:

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

2. No return value.

3. The compiler automatically calls the corresponding constructor when the object is instantiated.

4. The constructor can be overloaded.

class Date
 {
  public:
      // 1.无参构造函数
      Date()
     {}
  
      // 2.带参构造函数
      Date(int year, int month, int day)
     {
          _year = year;
5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦
用户显式定义编译器将不再生成。
          _month = month;
          _day = day;
     }
  private:
      int _year;
      int _month;
      int _day;
 };
  
  void TestDate()
 {
      Date d1; // 调用无参构造函数
      Date d2(2015, 1, 1); // 调用带参的构造函数
  
      // 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则编译器无法分析清楚函数声明还是调用
      // 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象
      // warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)
      Date d3();
}

      // Note: If you create an object through a no-argument constructor, there is no need to follow the object with parentheses, otherwise the compiler cannot analyze whether it is a function declaration or a function call
      // The function of the following code: the d3 function is declared, the function has no parameters, and returns A date type object
      // warning C4930: “Date d3(void)”: the prototype function was not called (was it intentionally defined with a variable?)
      Date d3();

5. If no constructor is explicitly defined in the class, the C++ compiler will automatically generate a default constructor with no parameters. Once the user explicitly defines the compiler, it will no longer generate it.

6. Both the parameterless constructor and the default constructor are called default constructors, and there can only be one default constructor .

Note: No-argument constructors, full default constructors, and constructors that we did not write to be generated by the compiler by default can all be considered default constructors.

7. The default constructor generated by the compiler is useless?

C++ divides types into built-in types (basic types) and custom types. The built-in type is the data type provided by the language, such as: int/char..., the custom type is the type we define ourselves using class/struct/union, etc. If you look at the following program, you will find that the compiler generates the default structure The function calls its default member function on the custom type member _t .

1.2 Destructor

  The destructor is the opposite of the constructor. The destructor does not destroy the object itself. The local object destruction is done by the compiler. When the object is destroyed, it will automatically call the destructor to complete the cleanup of resources in the object.

1.2.1 Features:

Destructors are special member functions that

1.2.2 Its characteristics are as follows:

1. The name of the destructor is to add the character ~ before the class name.

2. No parameters and no return type.

3. A class can have only one destructor. If not explicitly defined, the system will automatically generate a default destructor. Note: Destructors cannot be overloaded

4. When the life cycle of the object ends, the C++ compilation system automatically calls the destructor.

5. 

Built-in type members: No need to clean up resources when destroying, and finally the system can directly reclaim its memory;

For custom types: if an object of a class also has an object inside, the object of the class contained in it must be destroyed, so the destructor corresponding to this class must be called.

6. If there is no resource application in the class, the destructor can not be written, and the default destructor generated by the compiler can be used directly, such as the Date class; when there is a resource application, it must be written, otherwise it will cause resource leakage, such as the Stack class .

1.3 copy constructor

1.3.1 Concept:

There is only a single formal parameter, which is a reference to the object of this class type (usually const decoration is commonly used), and is automatically called by the compiler when creating a new object with an existing class type object .

1.3.2 Features: The copy constructor is also a special member function

1.3.3 Features are as follows:

1. The copy constructor is an overloaded form of the constructor.

2. The parameter of the copy constructor is only one and must be a reference to a class type object, and the compiler will directly report an error if the method of passing by value is used , because it will cause infinite recursive calls.

3. If not explicitly defined, the compiler will generate a default copy constructor. The default copy constructor object is copied in byte order according to memory storage. This kind of copy is called shallow copy, or value copy.

#include<stdlib.h>
#include<iostream>

class Date
{
private:
    // 基本类型(内置类型)
    int _year = 2023;
    int _month = 4;
    int _day = 4;
    // 自定义类型
    Time _t;
};
class Time
{
public:
    Time()
    {
        _hour = 1;
        _minute = 1;
        _second = 1;
        //    注意:在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定
        //    义类型是调用其拷贝构造函数完成拷贝的。
    }
    Time(const Time& t)
    {
        _hour = t._hour+1;
        _minute = t._minute+1;
        _second = t._second+1;
        std::cout << "Time::Time(const Time&)" << std::endl;
    }
private:
    int _hour;
    int _minute;
    int _second;
};

int main()
{
    Date d1;//构造函数

    // 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
    // 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数
        Date d2(d1);
    return 0;
}

 In fact, the default copy constructor generated by Time can also be used here.

class Time
{
public:
    Time()
    {
        _hour = 1;
        _minute = 1;
        _second = 1;
    }
    //Time(const Time& t)
    //{
    //    _hour = t._hour+1;
    //    _minute = t._minute+1;
    //    _second = t._second+1;
    //    std::cout << "Time::Time(const Time&)" << std::endl;
    //}
private:
    int _hour;
    int _minute;
    int _second;
};
class Date
{
private:
    // 基本类型(内置类型)
    int _year = 2023;
    int _month = 4;
    int _day = 4;
    // 自定义类型
    Time _t;
};
int main()
{
    Date d1;//构造函数

    // 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数
    // 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数
        Date d2(d1);
    return 0;
}

4. If the resource application is not involved in the class, the copy constructor can be written or not; once the resource application is involved, the copy constructor must be written, otherwise it is a shallow copy.

5. Typical calling scenarios of copy constructor:

1. Create a new object using an existing object

2. The function parameter type is a class type object

3. The return value type of the function is a class type object

1.4 Assignment operator overloading

1.4.1 The concept of 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 its return value type, function name, and parameter list. The return value type and parameter list are similar to ordinary functions. The function name is: the keyword operator followed by the operator symbol that needs to be overloaded.

Function prototype: return value type operator operator (parameter list)

The operator is overloaded into a global function. Note that there is no this pointer when overloading into a global function, and two parameters are required.

bool operator==(const Date& d1, const Date& d2)
{
    return d1._year == d2._year
   && d1._month == d2._month
        && d1._day == d2._day;
}

But this is a global operator==, how to ensure its encapsulation?

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)
    // 这里需要注意的是,左操作数是this,指向调用函数的对象
    bool operator==(const Date& d2)
 {
        return _year == d2._year;
            && _month == d2._month
            && _day == d2._day;
 }
private:
 int _year;
 int _month;
 int _day;
};

Notice:

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

2. An overloaded operator must have a class type parameter for an operator of a built-in type, and its meaning cannot be changed.

For example: the built-in integer + cannot change its meaning. When it is overloaded as a class member function, its formal parameter seems to be 1 less than the number of operands, because the first parameter of the member function is hidden this .* :: sizeof ?: . Note that the above 5 operators cannot be overloaded.

1.4.2 Assignment operator overloading:

1. Assignment operator overload format

Parameter type: const T&, passing by reference can improve the efficiency of parameter passing

Return value type: T&, return reference can improve the efficiency of return, and the purpose of return value is to support continuous assignment

Check whether you assign a value to yourself: *this! =d1;

Return *this: to compound the meaning of continuous assignment

2. The assignment operator can only be overloaded as a member function of a class and cannot be overloaded as a global function

Reason: If the assignment operator is not explicitly implemented, the compiler will generate a default one. At this time, if the user implements a global assignment operator overload outside the class, it will conflict with the default assignment operator overload generated by the compiler in the class, so the assignment operator overload can only be a member function of the class.

3. When the user does not explicitly implement

The compiler will generate a default assignment operator overload that copies byte-for-byte by value.

Notice:

1. Built-in type member variables are directly assigned, while custom type member variables need to call the assignment operator overload of the corresponding class to complete the assignment.

2. If resource management is not involved in the class, it doesn't matter whether the assignment operator is implemented; once resource management is involved, it must be implemented.

1.4.3 Pre-++ and post-++ overloading

1. Preposition ++: Return the result after +1
 Note: The object pointed to by this will not be destroyed after the function ends, so return it by reference to improve efficiency


 Date& operator++()
 {
 _day += 1;
 return *this;
 }

 2. Rear ++

Both pre-++ and post-++ are unary operators, in order to allow pre-++ and post-++ to be correctly overloaded

C++ stipulates that an additional parameter of type int is added when the post ++ is overloaded, but this parameter does not need to be passed when calling the function, and the compiler automatically
passes it
 . Note: post ++ is used first and then +1, so it needs to be returned before +1 Therefore, it is necessary to save
a copy
of this before implementing it , and then give this+1
 and temp is a temporary object, so it can only be returned by value, not by reference


 Date operator++(int)
 {
 Date temp(*this);
 _day += 1;
 return temp;
 }

1.5 const members

The const-modified "member function" is called a const member function. The const-modified class member function actually modifies the implicit this pointer of the member function, indicating that any member of the class cannot be modified in the member function.

1.6 Address and const address operator overloading

These two default member functions generally do not need to be redefined, and the compiler will generate them by default.

These two operators generally do not need to be overloaded, just use the default address overload generated by the compiler. Only in special cases, overloading is required, such as wanting others to obtain the specified content!

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

2. Initialization list

Initialization list: Starts with a colon, followed by a comma-separated list of data members, each "member variable" followed by an initial value or expression enclosed in parentheses.

Date(int year, int month, int day)

     : _year(2023)
     , _month(4)
     , _day(4)
 {}

Notice:

1. Each member variable can only appear once in the initialization list (initialization can only be initialized once)

2. The class contains the following members, which must be placed in the initialization list for initialization:

Reference member variables const member variables custom type members (and when the class has no default constructor)

3. Try to use the initialization list to initialize, because no matter whether you use the initialization list or not, for custom type member variables, you must first use the initialization list to initialize.

4. The order in which member variables are declared in the class is the order in which they are initialized in the initialization list , regardless of their order in the initialization list

2.1 explicit keyword

Constructors can not only construct and initialize objects, but also have the function of type conversion for a single parameter or a constructor with default values ​​except for the first parameter, which has no default value.

The following is an example of the implicit type conversion of the multi-parameter constructor specified by C++11

The same is true for single-argument constructors

using namespace std;

class A {
public:
	A(int a, int b,int c)
		: _year ( a),
	      _month (b),
	      _day (c)
	{

	}
	A(const A& a)
	{
		cout << "const A& " << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	A a = {1,2,3};
}

1. Single-parameter/multi-parameter constructor, without explicit modification, has type conversion function

 explicit modified constructor, prohibiting type conversion

3. static members

3.1 Concept:

Class members declared static are called static members of the class, member variables modified with static are called static member variables; member functions modified with static are called static member functions. Static member variables must be initialized outside the class. Interview question: Implement a class and calculate how many class objects are created in the program.

3.2 Features

1. Static members are shared by all class objects, do not belong to a specific object, and are stored in the static area

2. Static member variables must be defined outside the class. The static keyword is not added when defining, and only declared in the class

3. Class static members can be accessed with class name:: static member or object. static member

4. Static member functions have no hidden this pointer and cannot access any non-static members

5. Static members are also members of the class, limited by public, protected, and private access qualifiers

1. Can a static member function call a non-static member function? Can't

2. Can a non-static member function call a static member function of a class? Can

Example: To find 1+2+3+...+n, it is required not to use keywords such as multiplication and division, for, while, if, else, switch, case, and conditional judgment statements (A?B:C).

use static member variables


using namespace std;


class Sum
	{
	public:
		Sum()
		{
			_sum += _n;
			++_n;
		}
	
		static int GetSum()
		{
			return _sum;
		}
	private:
		static int _n;
		static int _sum;
	};
	
	class Solution {
	public:
		int Sum_Solution(int n) {
			Sum* p = new Sum[n];
			return Sum::GetSum();
		}
		~Solution()
		{
			cout << "~Solution()" << endl;
		}
	};
	int Sum::_n = 1;
	int Sum::_sum = 0;
	int main()
	{
		cout << Solution().Sum_Solution(100) << endl;
	}

Do not use static member variables

class Solution {
public:
    int Sum_Solution(int n) {
        //通过与运算判断n是否为正数,以结束递归
        n && (n += Sum_Solution(n - 1));
        return n;
    }
};

4. Inner classes

Concept: If a class is defined inside another class, the inner class is called an inner class. The inner class is an independent class, it does not belong to the outer class, let alone access the members of the inner class through the object of the outer class. Outer classes do not have any privileged access to inner classes.

Note: The inner class is the friend class of the outer class. See the definition of the friend class. The inner class can access all members of the outer class through the object parameters of the outer class. But the outer class is not a friend of the inner class.

characteristic:

1. The inner class can be defined as public, protected, or private in the outer class.

2. Note that the inner class can directly access the static members of the outer class without the object/class name of the outer class.

3. sizeof (external class) = external class , has nothing to do with the inner class.

Inner class encapsulation of the above example

class Solution {

  public:

    class Sum {
      public:
        Sum() {
            _sum += _n;
            ++_n;
        }

        static int GetSum() {
            return _sum;
        }

    };
    int Sum_Solution(int n) {
        Sum* p = new Sum[n];
        return Sum::GetSum();
    }
    ~Solution() {
        cout << "~Solution()" << endl;
    }
  private:
    static int _n;
    static int _sum;
};
int Solution::_n = 1;
int Solution::_sum = 0;

5. Some compiler optimizations when copying objects

In the process of passing parameters and returning values, generally the compiler will do some optimizations to reduce the copying of objects, which is still very useful in some scenarios.

5.1 Summary of Object Returns

1. For the object that accepts the return value, try to use the copy construction method to receive it, and do not assign it to receive it.

2. When returning an object in a function, try to return an anonymous object.

5.2 Summary of function parameter passing

Try to use const & parameter passing.

6. Anonymous objects

But we can define anonymous objects in this way. The characteristics of anonymous objects do not need to be named, but their life cycle only has this line

		cout << Solution().Sum_Solution(100) << endl;

Guess you like

Origin blog.csdn.net/m0_74234485/article/details/129959025