c + + basic notes

catalogue

==c + + basic notes==


</pre>
Assignment operators have =, + =, - =, * =, / =,% = < br > functions: for example, a+=2 is equivalent to a=a+2, and so on
</pre>
<br>
=====Comparison operator=====


Operator     meaning     example     result
 ==         equal     4==3       0
 !=         Unequal   4!= three       one
 <         Less than     4<3       0
 >         Greater than     4>3       one
 <=       Less than or equal to   4<=3       0
 >=       Greater than or equal to   4>=3       one
</pre>
=====Logical operator=====
! It is logical non, for example, there is event A. if a is true, then! A is false (Note: in c + +, all numbers except 0 are true, int a = 10, then! a = 0,!!a = 1) < br > & & are logical and, for example, there are events a and b. If a and b are true at the same time, the result is true. < br > | is logical or, for example, there are events a and b. If a or b is true, then a| b is true
=====Program flow structure=====
c + + supports three basic program structures: sequence structure, selection structure and loop structure < br > 1. Sequence structure: programs are executed in sequence without jump < br > 2. Selection structure: corresponding functions are executed selectively according to whether the conditions are met < br > 3. Loop structure: a code is executed repeatedly according to whether the conditions are met
======if statement======
Single line format if statement: if (condition) {statement executed when the condition is met} < br > multi line format if statement: if (condition) {statement executed when the condition is met} else {statement executed when the condition is not met} < br > multi condition if statement < br > nested if statement: add an IF statement to the if condition

//Multi conditional if statement
#include<iostream>
using namespace std;
int main()
{
    //Enter a score. If the score is greater than or equal to 500, it will be regarded as having been admitted to one university, and if the score is greater than or equal to 300, it will be regarded as having been admitted to two universities, otherwise it will be regarded as not having been admitted to the University
    int score = 0;
    cout << "Please enter your score" << endl;
    cin >> score;
    cout << "The score you entered is" << score << endl;
    if (score >= 500)
    {
        cout << "Congratulations on your admission to a university" << endl;
        if (score > 700)
        {
            cout << "You can be admitted A university" << endl;
        }
        else if (score > 650)
        {
            cout << "You can be admitted B university" << endl;
        }
        else if (score > 600)
        {
            cout << "You can be admitted C university" << endl;
        }
    }
    else if (score >= 300)
    {
        cout << "Congratulations on your admission to the second university" << endl;
    }
    else


    {
        cout << "I'm sorry you didn't go to college" << endl;
    }
    system("pause");
    return 0;
}


How to obtain the individual, ten and hundred digits of a three digit number: < br > # take a three digit number to 10 to obtain the three digits< Br > # divide a three digit number by 10, and then modulo it to 10 to get the ten digits of the three digit number; (in c + +, the division of two integers is still an integer, and the decimal part is removed) < br > # divide a three digit number by 100 to get the hundredth of the three digit number.
<br>
View the code of ASCII value: cout < < (int) variable < < endl;
ASCII value: a corresponds to 97, a corresponds to 65, recursive in turn
=====Escape character=====
Common escape characters:
*\n is a newline character < br > * \ t is a horizontal tab character < br > * \ \ is a backslash character "\"
=====Ternary operator=====
Function: simple judgment is realized through the ternary operator < br > syntax: expression 1? Expression 2: expression 3 (Note: the variables returned by the ternary operator in c + + can be assigned continuously)

//ternary operator 
#include<iostream>
using namespace std;
int main()
{

    int a = 10;
    int b = 20;
    (a > b ? a : b) = 100;
        
    cout <<"a="<< a << endl;   //a=10
    cout << "b=" << b << endl; //b=100


    system("pause");
    return 0;
}


=====switch statement=====
Function: execute multi condition branch statement < br > syntax: switch (expression) < br > {< br > case result 1: execute statement; break; < br > case result 2: execute statement; break; < br >... < br > Default: execute statement; break; < br >}

//Practice of switch statement
#include<iostream>
using namespace std;
int main() {

    //switch Statements 
    int score = 0;
    cout << "Please rate the movie" << endl;
    cin >> score;
    cout << "Your score is:" << score << endl;
    switch (score)
    {
    case 10:
        cout << "What do you think is a classic movie" << endl;
        break;    //Used to exit the current branch
    case 9:cout << "What do you think is a classic movie" << endl; break;
    case 7:cout << "Do you think movies are better" << endl; break;
    case 6:cout << "Do you think movies are average" << endl; break;
    case 5:cout << "Do you think movies are average" << endl; break;
    default:cout << "Do you think the film is bad" << endl; break;
    }

    system("pause");
    return 0;
}


=====Cyclic structure=====
======while loop statement======
Syntax: < br > while < br > {loop statement}

//while loop statement
#include<iostream>
using namespace std;
int main(){
    
    //while loop statement
    int a = 0;
    while (a < 10)
    {
        cout << a << endl;
        a++;
    }

    system("pause");
    return 0;
}


======Add small points======
rand()% 100 represents a random number from 0 to 99; rand()% 100 + 1 represents a random number from 1 to 100
=====do...while loop statement=====
Syntax: do {execute statement}   while (cycle condition);

//do...while statement exercise: find out the number of all daffodils
#include<iostream>
using namespace std;
int main()
{
    
    //Use the do...while loop statement to get the total number of daffodils
    
    //1. Print all three digits
    int num = 100;
    do
    {
        //2. Find all the daffodils from all the three digits
        int a = 0;  //A single bit used to obtain three digits
        int b = 0;  //Ten digits for obtaining three digits
        int c = 0;  // Used to obtain three digit hundredths

        a = num % 10;
        b = num / 10 % 10;  //When two integers are divided, the result is not an integer. If there is a decimal, the decimal part will be removed
        c = num / 100;
        if (a*a*a+b*b*b+c*c*c==num)
        {
            cout << num << endl;
        }
        num++;
    }     while (num < 1000);
    

    system("pause");
    return 0;
}


 

//Circular sentence exercise: design a number guessing game
#include<iostream>
using namespace std;
#include<ctime>     // The system time header file contains
int main() {

    //Design a number guessing game

    srand((unsigned int)time(NULL));   //srand is used to add random number seeds. Its function is to generate random numbers by using the current system time to prevent the random numbers from being the same every time
    int num = rand() % 100 + 1;  //rand()%100 represents a random number from 0 to 99
    //cout << num << endl;
    int val = 0;
    cout << "Please enter the number you guessed" << endl;

    while (1)
    {
        cin >> val;

        if (val > num)
        {
            cout << "Guess too much" << endl;
        }
        else if (val < num)
            {
                cout << "Guess too small" << endl;
            }
        else if(val=num)
        {
            cout << "Congratulations, you guessed right" << endl;
            break;  //break, use this keyword to exit the current loop
        }
    }

    system("pause");
    return 0;
}


=====for loop=====
Function: execute loop statements when loop conditions are met
Syntax: for (start expression; conditional expression; end loop body) < br > {loop statement}

//for statement exercise
#include<iostream>
using namespace std;
int main() {

    //for loop statement exercises, including nested structures
    for (int i = 1; i <= 100; i++)
    {
        '''''if (i % 7 ==0||i%10==7||i/10==7)'''''
        {
            cout << "Knock on the table" << endl;
        }
        else {
            cout << i << endl;
        }    
    }

    system("pause");
    return 0;
}


=====Jump statement=====
1. Break < br > 2. Continue statement < br > function: in the loop statement, skip the remaining unexecuted statements in this loop and continue to execute the next loop < br > 3. Goto statement < br > function: if the tag exists, when executing the goto statement, it will jump to the location of the tag
=====One dimensional array name=====
Purpose of a dimension group name: < br > 1. It can count the length of the entire array in memory < br > 2. It can obtain the first address of the array in memory < br > / / arr [0] for accessing the first element; The address of the first element in the array is (int) & arr [0]; Get the first address: cout < < (int) arr < < endl;

//Application of one-dimensional array 1: find the largest element in the array
#include<iostream>
using namespace std;
int main() {

    //sizeof array name
    int arr[5] = { 300,350,200,400,250 };
    int max = 0;
    for (int i = 0; i <= 4; i++)
    {
        if (max < arr[i])
        {
            max = arr[i];
        }
    }
    cout << "max=" << max << endl;


    system("pause");
    return 0;
}


 

//One dimensional array application 2: inversion of array elements (using nested loops of for statements)
#include<iostream>
using namespace std;
int main() {

    //Implement the inverse of array elements
    int arr[5] = { 1,3,2,5,4 };
    cout << "Array elements before inverse:" << endl;
    for (int i = 0; i < 5; i++)
    {
        cout << arr[i]<<" ";
    }

    int start = 0;
    int end = sizeof(arr) / sizeof(arr[0]) - 1;

    while (start < end)
    {
        int temp = arr[start];
        arr[start] = arr[end];
        arr[end] = temp;
        start++;
        end--;
    }
    cout << endl;

    cout << "Inverted array element:" << endl;
    for (int j = 0; j < 5; j++)
    {
        cout << arr[j] << " ";
    }

    system("pause");
    return 0;
}


=====Bubble sorting=====
Function: it is the most commonly used sorting algorithm to sort the elements in the array < br > 1. Compare the adjacent elements. If the first is larger than the second, exchange the two / / inner loops. The number of inner loops in each outer loop: total number of elements - number of outer loops - 1 < br > 2. Do the same for each pair of adjacent elements. After execution, Find the first maximum value / / number of external cycles: total elements - 1 < br > 3. Repeat the above steps. The number of comparisons is - 1

//Bubble sorting exercise: sort a group of numbers from large to small
#include<iostream>
using namespace std;
int main() {

    
    int arr[9] = { 4,2,8,0,5,7,1,3,9 };
    for (int a = 0; a < 9; a++)
    {
        cout << arr[a] << " ";
    }
    cout << endl;


    //External loop. The total number of sorting rounds is - 1
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]) - 1; i++)
    {

        //Internal circulation   Comparison times: number of elements - current rounds - 1
        for (int j = 0; j < sizeof(arr) / sizeof(arr[0]) - i - 1;j ++ )
        {
            if (arr[j] < arr[j + 1])
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }

        }
    }

    //Print sorted results
    cout << "The sorted result is" << endl;
    for (int b = 0; b < 9; b++)
    {
        cout << arr[b] << " ";
    }
    cout << endl;

    system("pause");
    return 0;
}


=====Two dimensional array=====
Matrix can be printed by nested loop: < br > definition method of two-dimensional array: < br > 1. Data type   Array name [number of rows] [number of columns], and then write them one by one, for example, arr [0] [0] = 3< Br > 2. Data type   Array name [rows] [columns] = {data1, data2}, {data3, Data4}} < br > 3, datatype   Array name [number of rows] [number of columns] = {data 1, data 2, data 3, data 4} < br > 4. Data type array name [] [number of columns] = {data 1, data 2, data 3, data 4}

//Role of double digit group names
#include<iostream>
using namespace std;
int main() {
    
    int arr[2][3] =
    {
        {1,2,3},
        {4,5,6}
    };

    //1. View memory footprint
    cout << "The memory space occupied by the two-dimensional array is " << sizeof(arr) << endl;
    cout << "The memory space occupied by the first row of the two-dimensional array is " << sizeof(arr[0]) << endl;
    cout << "The memory space occupied by the first element of the two-dimensional array is " << sizeof(arr[0][0]) << endl;
    cout << "The number of rows of the two-dimensional array is " << sizeof(arr) / sizeof(arr[0]) << endl;
    cout << "The number of columns in a two-dimensional array is " << sizeof(arr[0]) / sizeof(arr[0][0])<<endl;

    //2. View the first address of a two-dimensional array
    cout << "The first address of the two-dimensional array is " << (int)arr << endl;
    cout << "The first address of the first row of the two-dimensional array is " <<(int) arr[0] << endl;

    system("pause");
    return 0;
}


=====Functions=====
Function: encapsulate a piece of frequently used code to reduce repeated code < br > a large program is generally divided into several program blocks, and each module realizes specific functions
======Function definition and call======
1. return value type < br > 2. Function name < br > 3. Parameter list < br > 4. Function body statement < br > 5. return expression
Syntax:
Return value type   Function name (parameter list)
{
Function body statement
return expression
}

//Function definition and call
#include<iostream>
using namespace std;

//Define an addition function
//When defining a function, num1 and num2 have no real data. They are just formal parameters, which are called formal parameters for short
int add(int num1, int num2)
{
    int sum = num1 + num2;
    return sum;
}


int main() {

    //Call the defined addition function
    int a = 10;
    int b = 20;
    int c = add(a, b);    //a and b are actual parameters, which are called actual parameters for short     When the function is called, the value of the argument is passed to the formal parameter
    cout << " c = " << c << endl;

    system("pause");  //Print "press any key to continue"
    return 0;
}

======Value transfer======
The so-called value transfer means that the real parameter passes the value to the formal parameter during function call < br > / / if the formal parameter changes during value transfer, it will not affect the actual parameter < br > summary: the formal parameter cannot modify the actual parameter during value transfer
Common styles of functions < br > 1, no return without parameters < br > 2, no return with parameters < br > 3, no return without parameters < br > 4, return with parameters

//pass by value
#include<iostream>
using namespace std;

//Value transfer: define a function to exchange two numbers

void swap(int num1, int num2)    //If the function does not need to return a value, you can write void when declaring
{
    cout << "Before exchange: " << endl;
    cout << "num1= " << num1 << endl;
    cout << "num2= " << num2 << endl;
    int temp = num1;
    num1 = num2;
    num2 = temp;
    cout << "After exchange: " << endl;
    cout << "num1= " << num1 << endl;
    cout << "num2= " << num2 << endl;
    return;  //When the return value is not needed, you can not write return
}

int main() {

    int a = 10;
    int b = 20;
    cout << "a= " << a << "  " << "b= " << b << endl;
    swap(a, b);
    cout << "a= " << a << "  " << "b= " << b << endl;
    //When the value is passed, the formal parameters of the function are changed and the arguments will not be affected

    system("pause");
    return 0;
}


======Declaration of function======
If the function definition appears after the main function, first make the function declaration in the main function. Use of < br > declaration: return value type   Function name (parameter list) < br > note: the declaration can be written multiple times, but the definition can only be written once
======Function sub file writing======
Function: make the code structure clearer < br > there are generally four steps to write functions in files < br > 1. Create a. h header file < br > 2. Create a. cpp source file < br > 3. Write the declaration of functions in the header file < br > 4. Write the definition of functions in the source file
=====Pointer=====
Function: access memory indirectly through pointer
You can save an address through a pointer
Syntax of pointer definition: data type  *   Pointer variable name int * p;
  int a = 10;     Let the pointer record the address P = & A of variable a   (& is addressing symbol)  // int * p  = & a;

//Pointers and arrays
#include<iostream>
using namespace std;
int main() {

    int a = 10;
    int b = 20;

    //1. const modifies pointers, which are called constant pointers     At this time, the pointer can be modified, and the value pointed by the pointer cannot be modified
    const int* p1 = &a;
    cout << "*p1= " << *p1 << endl;
    //*p = 20 error
    p1 = &b;
    cout << "*p1= " << *p1 << endl;

    //2. const modifies constants, which are called pointer constants     At this time, the pointer cannot be modified, and the value pointed to by the pointer can be modified
    int* const p2 = &a;
    cout << "*p2= " << *p2 << endl;
    *p2 = 20;
    //P = & B; error
    cout << "*p2= " << *p2 << endl;

    //3. const modifies both pointers and variables
    const int* const p3 = &a;
    //The point of the pointer cannot be modified, and the value pointed to by the pointer cannot be modified

    system("pause");
    return 0;
}


=====Use of pointers=====
You can find the memory pointed to by the pointer by dereferencing
Adding * before the pointer means to dereference the data in memory pointed to by the pointer * p
In the 32-bit operating system, the pointer occupies 4 bytes of space. No matter what the data type, in the 64 bit operating system, the pointer occupies 8 bytes of space
=====Null pointer and wild pointer=====
Null pointer: pointer variable points to the space numbered 0 in memory   int * p = NULL; (the memory number between 0 and 255 is occupied by the system and is therefore inaccessible)
Function: initialize memory variables
Note: the memory pointed to by the null pointer is inaccessible
Wild pointer: pointer variable points to illegal memory space
=====const modifier pointer=====
const modifies pointers, which are called constant pointers
int a = 10; int b = 20;
Const int * P = & A; constant pointer
Features: the pointer can be modified, but the value pointed by the pointer cannot be changed   * p = 20, error; P = & B, correct
Const modifier constant pointer constant int * const P = & A;
Features: the pointer cannot be modified, but the value pointed by the pointer can be modified     * p = 20, correct; P = &b, error
const modifies both pointers and constants
Features: the pointer and the value pointed by the pointer cannot be modified  
const int * const p = &a;         * p = 20, error; P = & B, error  
=====Pointers and arrays=====
Pointer to array

//Pointers and arrays
#include<iostream>
using namespace std;
int main() {

    int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
    cout << "First element " << arr[0] << endl;

    int* p = arr;   //Pointer to array
    cout << "Access the first element with a pointer" << *p << endl;

    int* p2 = arr;
    for (int i = 0; i < 10; i++)
    {
        cout << "Read array with pointer " << *p2 << endl;
        p2++;
    }

    system("pause");
    return 0;
}


=====Address delivery=====
Address passing can modify arguments   Write the parameter list of a function with a pointer

//Pointer bubble sort and array
#include<iostream>
using namespace std;

//Bubble sorting      Parameter 1 first element of array    Parameter 2 array length
void bubbleSort(int* arr, int len)
{
    for (int i = 0; i < len - 1; i++)
    {
        for (int j = 0; j < len - i - 1; j++)
            if (arr[j] > arr[j + 1])
            {
                int temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
    }
}

void printArray(int* arr, int len)
{
    for (int a = 0; a < len; a++)
    {
        cout << arr[a] << endl;
    }
}

int main() {

    int arr[10] = { 4,3,6,9,1,2,10,8,7,5 };
    int len = sizeof(arr) / sizeof(arr[0]);
    
    bubbleSort(arr, len);
    printArray(arr, len);

    system("pause");
    return 0;
}


=====Memory partition storage=====
During the execution of c + + programs, the memory is divided into four areas. < br >
Code area: it stores the binary code of the function and is managed by the operating system < br >
Global area: stores global variables, static variables and constants < br >
Stack area: automatically allocated and released by the compiler to store function parameter values, local variables, etc. < br >
Heap area: allocated and released by the programmer. If the programmer does not release it, it will be recycled by the operating system at the end of the program < br >
Significance of four memory areas: data stored in different areas gives us different life cycles and gives us greater flexibility in programming < br >
======Before running the program======
After the program is compiled, an exe executable program is generated. Before the program is executed, it is divided into two areas < br >
Code area: < br >
  Store machine instructions executed by CPU < br >
  The code area is shared. The purpose of sharing is to have only one code in memory for frequently executed programs < br >
  The code area is read-only because it prevents the program from accidentally modifying its instructions < br >
Global area: < br >
  Global and static variables are stored here < br >
  The global area also contains a constant area, where string constants and other constants are also stored < br >
  The data in this area is released by the operating system after the program ends < br > global variables, constants and static variables are stored in the global area, and local variables are stored in other areas < br >

//global variable
#include<iostream>
using namespace std;

//Create global variable
int g_a = 10;
int g_b = 20;

//const modified global variable, that is, global constant
const int c_g_a = 10;
const int c_g_b = 20;

int main()
{

    //Global area   Global variable   Constant static variable


    

    //Create normal local variables
    int a = 10;
    int b = 20;

    cout << "local variable a Address of: " << (int)&a << endl;
    cout << "local variable b Address of: " << (int)&b << endl;

    cout << "global variable g_a Address of: " << (int)&g_a << endl;
    cout << "global variable g_b Address of: " << (int)&g_b << endl;

    //Static variable    Add a static before a normal variable, which is a static variable
    static int s_a = 10;
    static int s_b = 20;

    cout << "Static variable s_a Address of: " << (int)&s_a << endl;
    cout << "Static variable s_b Address of: " << (int)&s_b << endl;

    //constant
    //string constant 

    cout << "Address of string constant: " << (int)&"hello world" << endl;

    //const modified variable
    //Const modified global variable, const modified local variable
    cout << "Global constant c_g_a Address of: " << (int)&c_g_a << endl;
    cout << "Global constant c_g_b Address of: " << (int)&c_g_b << endl;

    const int c_l_a = 10;
    const int c_l_b = 20;
    cout << "Local constant c_l_a Address of: " << (int)&c_l_a << endl;
    cout << "Local constant c_l_b Address of: " << (int)&c_l_b << endl;

    system("pause");
    return 0;
}


Summary: < br >
In c + +, the program is divided into global area and code area before running < br >
The code area is characterized by sharing and read-only < br >
The global area always stores global variables, static variables and constants < br >
The const modifier's global constant and string constant are stored in the constant
<br>
======After the program runs======
  Stack area: < br >    
    It is automatically allocated and released by the compiler to store the parameter values (including formal parameters) and local variables of the function < br >
Note: do not return the address of local variables. The data opened up in the stack area is automatically released by the compiler < br > heap area: < br >
    It is allocated and released by the programmer. If the programmer does not release it, it will be recycled by the operating system at the end of the program < br >
    In c + +, new is mainly used to open up memory in the heap < br >

//type
#include<iostream>
using namespace std;

int* func()
{
    int* p = new int(10);
}

int main() {

    //Using the new keyword, you can open up data to the heap
    //The pointer is also a local variable in nature. The data saved by the pointer is placed in the heap
    int* p = func();
    cout << *p << endl;

    system("pause");
    return 0;
}


======new operator======
  Using new operator in c + + to open up data in heap
  The data developed in the heap area is manually developed by the programmer, manually released, and released by using the operator delete
  Syntax: new data type
  The data created with new will return the pointer corresponding to the data

Using new to open up arrays in heap
 viod func()
 {
    int* arr = new int[10];  // 10 means that the array has 10 elements
   for(int i = 0;i<10;i++)
   {
     arr[i] = i;
   }
 }
  delete[] arr;   // When releasing an array, you need to add []
 int * func()
 {
   int * p = new int(10);
   return p;
 }
  delete p;   // Free heap memory = = = = = structure=====
Definition: it is a user-defined data type and allows users to store different data types
Syntax: struct structure name (structure member list)
<br>
There are three ways to create variables through structures
</pre>
1. struct structure name variable name
2. struct structure name variable name = {member 1 value, member 2 value...}
3. Create variables as you define the structure

//Definition and use of structure
#include<iostream>
#include<string>
using namespace std;

struct Student
{
    string name;
    int score;
    int age;
}s3;    //3. Create variables when creating structures

int main() {

    struct Student s1;

    //1. Struct structure name variable name; (it can be omitted when creating variables with struct structure)
    //Assign a value to the s1 attribute and access the attribute in the structure variable through "."
    s1.name = "Zhang San";
    s1.score = 100;
    s1.age = 18;
    cout << "full name: " << s1.name << " fraction " << s1.score << " Age " << s1.age << endl;

    //2. struct structure name variable name = {member 1 value, member 2 value...}
    struct Student s2 = { "Li Si",80,23 };
    cout << "full name: " << s2.name << " fraction " << s2.score << " Age " << s2.age << endl;

    s3.name = "Wang Wu";
    s3.score = 50;
    s3.age = 24;
    cout << "full name: " << s3.name << " fraction " << s3.score << " Age " << s3.age << endl;

    system("pause");
    return 0;
}


======Structure array======
Function: put the defined structure into the array to facilitate maintenance
Syntax: struct structure name array name [number of elements] = {{}, {}, {},

//Structure array
#include<iostream>
#include<string>
using namespace std;

struct Student
{
    string name;
    int age;
    int score;
};

int main()
{

    struct Student stuArray[3] =
    {
        {"Zhang San",18,100},
        {"Li Si",23,99},
        {"Wang Wu",24,66}
    };
    stuArray[2].name = "Zhao Liu";
    stuArray[2].age = 20;
    stuArray[2].score = 88;

    for (int i = 0; i < 3; i++)
    {
        cout << "full name: " <<stuArray[i].name << " Age " << stuArray[i].age << " fraction " <<stuArray[i].score << endl;
    }

    system("pause");
    return 0;
}


======Structure pointer======
Role: access members in a structure through a pointer
The operator '- >' allows you to access structure properties through the structure pointer
struct student s = {"Zhang San", 18100};
struct student *p = &s;
Accessing structure attributes with pointers: P - > name; P - > age; P - > score ============ structure nested structure======
In the definition of structure, another structure can be used as a member of this structure

//Structure nested structure
#include<iostream>
#include<string>
using namespace std;

struct student
{
    string name;
    int age;
    int score;
};

//Structure nested structure
struct teacher
{
    int id;
    string name;
    struct student stu;
};

int main() {

    teacher t;
    t.id = 140403;
    t.name = "Lao Wang";
    t.stu.name = "Li Si";
    t.stu.age = 18;
    t.stu.score = 100;

    cout << "Teacher's name " << t.name << " Teacher's employee number " << t.id << " Name of the student tutored by the teacher " << t.stu.name << endl;
    cout << "Student achievement " << t.stu.score << " Student age " << t.stu.age << endl;

    system("pause");
    return 0;
}


=======Structure as function parameter======
Value passing and address passing

//Value passing and address passing of structure pointer
#include<iostream>
#include<string>
using namespace std;

struct student
{
    string name;
    int age;
    int score;
};

void printstudent1(struct student s)
{
    cout << "full name: " << s.name << " fraction " << s.score << " Age " << s.age << endl;
}

void printstudent2(struct student* p)
{
    cout << "full name: " << p->name << " fraction " << p->score << " Age " << p->age << endl;
}
int main() {

    student s;
    s.name = "Li Si";
    s.age = 23;
    s.score = 100;

    printstudent1(s);     //Value passing, formal parameters cannot modify arguments
    printstudent2(&s);    //Address passing, formal parameters can modify arguments


    system("pause");
    return 0;
}


======const usage scenario in structure======
Function: use const to prevent misoperation
const student qualifies the structure and cannot be changed
=====Quote=====
Function: alias variables < br >
Syntax: data types  & Alias = original name < br >
int a = 10;<br>
int &b = a;<br>
Modifying the value of one of a or b will also change the value of the other < br >
Notes for reference < br >
References must be initialized < br >
References cannot be changed after initialization < br >

//Reference passing
#include<iostream>
using namespace std;

void mySwap(int& a, int& b)
{
    int temp = a;
    a = b;
    b = temp;
}

int main() {

    int a = 10;
    int b = 20;
    mySwap(a, b);
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;

    system("pause");
    return 0;
}


======Reference as function parameter======
Function: when passing a function, you can use the reference technology to make the formal parameter modify the argument < br >
Advantages: pointer modification arguments can be simplified < br >
Reference passing: formal parameters can modify arguments < br >
======Reference function return value======
Function: references can exist as function return values < br >
Note: do not return local variable references < br >
Usage: functions are used as lvalues < br >

//Reference function return value
#include<iostream>
using namespace std;

//Returns a reference to a static variable
int& test1()
{
    static int a = 10;
    return a;
}

int main() {

    //Function as an lvalue, you must return a reference
    int& b = test1();    //b=10

    test1() = 1000;     //b=1000


    system("pause");
    return 0;
}


======Constant reference======
Function: constant references are mainly used to modify formal parameters to prevent misoperation < br >
In the function parameter list, const can be added to modify the parameter to prevent the parameter from changing the argument < br >
const int & ref = 10;   After adding const, the compiler modifies the code to int temp = 10; int & ref = temp; < br >
Const int & Ref. after being modified with const, the value of ref cannot be modified < br >

=====Function default parameters=====
In c + +, the formal parameters in the formal parameter list of a function can have a default value of < br >
Syntax: return value type   Function name (parameter = default) {} < br >
If we pass in data in the argument, we will use the data we pass in. If not, we will use the default value < br >
If a location already has a default value, it must have a default value from left to right from this location < br >
If the function declaration has default parameters, the function implementation cannot have default parameters. Only one function declaration and function definition can have default parameters < br >

=====Function placeholder parameter=====
There can be placeholder parameters in the formal parameter list of functions in c + +, which are used for placeholder. Fill this position when calling functions < br >
Syntax: return value type function name (data type) {} < br >
Placeholder parameters can have default parameters < br >

=====Function overloading=====
Function: function names can be the same to improve reusability < br >
Function overload meets the following conditions: < br >
Under the same scope,
Same function name
Function parameters have different types, numbers or orders
Precautions: < br >
Reference as overload condition < br >
Function overload encounters function default parameters < br > = = = = = classes and objects=====
The three characteristics of c + + object-oriented are encapsulation, inheritance and polymorphism
======Encapsulation======
Meaning of encapsulation:
Take attributes and behaviors as a whole to express things in life
Control attributes and behaviors with permissions    

//Meaning of encapsulation
#include<iostream>
using namespace std;

const double PI = 3.14;

class circle    //Define a class and use class
{
    /*
    Access rights
    Public authority
    */
public:

    /*
    attribute
    radius
    */
    double m_r;

    /*
    Behavior (behavior is usually a function)
    Gets the circumference of the circle
    */
    double calculateZC()
    {
        return 2 * PI * m_r;
    }
};

int main() {

    //Create a specific circle (object) through the circle class
    circle c1;

    //Assign values to the attributes of the circle object
    c1.m_r = 5.20;
    cout << "circular c1 The perimeter of the is: " << c1.calculateZC() << endl;

    system("pause");
    return 0;
}


The second meaning of encapsulation:
During class design, attributes and behaviors can be controlled under different permissions < br >
There are three types of access rights: < br >
1,public   Public authority       It can be accessed inside the class and outside the class < br >
2. Protected protected permissions   It can be accessed inside the class, but not outside the class       Sons can access protected content in fathers < br >
3,private   Private rights       It can be accessed inside the class, but not outside the class     The son cannot access the father's private content < br >

#include<iostream>
using namespace std;

class student {

public:

    string name;
    int ID;

    void print() {

        cout << "Student's name: " << name << endl;
        cout << "Student ID: " << ID << endl;
    }
};


int main() {

    student s1;
    s1.name = "Zhang San";
    s1.ID = 173962;
    s1.print();

    student s2;
    s2.name = "Li Si";
    s2.ID = 174615;
    s2.print();

    system("pause");
    return 0;
}

======The difference between struct and class======
In c + +, the only difference between struct and class is that the default access permissions are different < br >
The default permission of struct is public < br >
class the default permission is private < br >
======Set member properties to private======
Advantages: set all member properties to private, and you can control the read and write permissions yourself. For write permission, we can check the validity of data < br >
Put the member attribute under private. If you want to change the attribute, put the corresponding function under public < br >
=====Object initialization and cleanup=====
Constructors and destructors: initialization and cleanup < br >
If we do not provide constructs and destructors, the compiler will provide compiler automatic mobilization. Spatiotemporal implementation of constructors and destructors provided by the compiler < br >
Constructor: its main function is to assign value to the member attribute of the object when creating the object. The constructor is automatically called by the compiler without manual call < br >
Destructor: it is mainly used to automatically call and perform some cleaning work before object destruction < br >
Constructor syntax: class name () {} < br >
1. Constructor, no return value and no void < br >
2. The function name is the same as the class name < br >
3. Constructors can have parameters, so overloading can occur < br >
4. When calling an object, the program will automatically call the constructor without manual call, and will only call it once < br >
Destructor syntax: ~ class name () {} < br >
1. The destructor does not return a value nor write void < br >
2. The function name is the same as the class name. Add ~ < br > before the name
3. Destructors cannot have parameters, so overloading is not allowed < br >
4. The program will automatically call the destructor before the object is destroyed without manual call, and will only call once < br > = = = = = classification and call of constructor=====
Two classification methods: < br >
    It can be divided into parametric structure and nonparametric structure by parameters < br >
    It can be divided into ordinary structure and copy structure by type < br >

 class person
 {
 public:
   person( )
  {
     cout<<"person Parameterless constructor call"<<endl;
  }
  
  person( int a)
  {
    cout<<"person Parameterized constructor call"<<endl;
    age = a;
  }

  person( const person &p)
  {
    age = p.age;      //Copy all the attributes of the incoming person to me
  }
  
  ~person( )
  {
     cout<<"person Destructor call for"<<endl;
  }

   int age;
 };


Three calling methods: Bracket Method   Display method   Implicit transformation method
Call:
void test1( )
  {
   // 1. Bracket method
    person p1;            // Default constructor call, call parameterless constructor               Note: when calling the default constructor, do not add (); Do not use copy functions to initialize anonymous objects
    person p2(10);     // Call parameterized constructor
    person p3(p2);    // Call copy constructor

   // 2. Display method
    person p1;                // Call parameterless construction
    person p2 = person(10);    // Call parameterized construction
    person p3 = person(p3);   // Call copy construct

Anonymous objects, such as person(10)   Feature: after the current line executes the structure, the system will immediately recycle the anonymous object
   // 3. Implicit transformation method
    person p4 = 10;    // It is equivalent to writing person p4 = person(10);   Call parameterized constructor
    person p5 = p4;    // Call copy constructor
  }===== Basic concepts of STL=====
STL (standard template library) < br >
STL is broadly divided into container, algorithm and iterator < br >
Containers and algorithms are seamlessly connected through iterators < br >
Almost all STL codes adopt template classes and template functions < br >
======STL six components======
They are container, algorithm, iterator, functor, adapter (adapter) and space configurator < br >
1. Container: various data structures, such as vector, list, deque, set, map, etc., are used to store data < br >
2. Algorithm: various commonly used algorithms, such as sort, find, copy and for_each et al. < br >
3. Iterator: acts as the glue between the container and the algorithm < br >
4. Imitation function: it behaves like a function and can be used as a strategy of the algorithm < br >
5. Adapter: something used to decorate a container or an interface of a functor or iterator < br >
6. Space configurator: responsible for space configuration and management < br >
======Container algorithm iterator======
=======vector stores built-in data types=======
Container: vector < br >
Algorithm: for_ each<br>
Iterator: vector < int >:: iterator < br >

//Use vector container to store data and realize data traversal
#include<iostream>
using namespace std;
#include<vector>

//The first traversal method
void test1()
{
  //Create a vector container and treat the container as an array
    vector<int> v;

    //Insert data into container
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);

    //Accessing data in a container through an iterator
    vector<int>::iterator itBegin = v.begin();    //v.begin () is the starting iterator, pointing to the first element of the container
    vector<int>::iterator itEnd = v.end();   //v.end() is the end iterator, pointing to the next position of the last element in the container

    while (itBegin != itEnd)
    {
        cout << *itBegin << endl;
        itBegin++;
    }
    //The second traversal method


    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << endl;
    }
}

int main() {

    test1();

    system("pause");
    return 0;
}


=====Copy construction=====
There are usually three times to call the copy constructor:
1. Initialize an object with an object that has been created
2. Values are passed to function parameters
3. Returns a local object as a value

//Copy constructor call timing
#include<iostream>
using namespace std;


class person {

public:
    person()
    {
        cout << "person Parameterless constructor call" << endl;
    }

    person(int age)
    {
        m_age = age;
        cout << "Call with parameter constructor" << endl;
    }

    person(const person & p)
    {
        m_age = p.m_age;
        cout << "Copy constructor call" << endl;
    }

    ~person()
    {
        cout << "person Destructor call" << endl;
    }
private:
    int m_age;

};


int main() {

    //Situation 1
    person p1(10);
    person p2(p1);

    system("pause");
    return 0;
}


=====Constructor call rule=====
By default, the c + + compiler adds at least three functions to a class < br >
1. Default constructor (no parameters, empty function body) < br >
2. Default destructor (no parameters, empty function body) < br >
3. The default copy constructor copies the values of attributes < br >
Constructor calling rules are as follows: < br >
If the user defines a parametric constructor, c + + no longer provides a parameterless constructor, but provides a default copy constructor < br >
If you define a copy constructor, c + + will not provide another constructor < br >
=====Deep and shallow copies=====
Shallow copy: simple assignment copy operation < br >
Deep copy: re apply for space in the heap area and copy < br >
The problem caused by shallow copy is that the heap memory is repeatedly released. The problem of shallow copy should be solved by deep copy < br >

//Solve the problem of shallow copy with deep copy
#include<iostream>
using namespace std;

class Person
{

public:
    Person()
    {
        cout << "Person Default constructor call" << endl;
    }

    Person(int age, int height)
    {
        m_age = age;
        m_height = new int(height);       //Use the new operator to open up data in the heap
        cout << "Person Call with parameter constructor" << endl;
    }

    //Create your own copy constructor to solve the problems caused by shallow copy
    Person(const Person& p)
    {
        cout << "Person Copy constructor call" << endl;
        m_age =p.m_age;
        /*m_height = p.m_height;*/   //The compiler's default implementation is this line of code

        m_height = new int(*p.m_height);
    }

    ~Person()              //Destructor to release the data office opened in the heap area
    {
        if (m_height != NULL)
        {
            delete m_height;
            m_height = NULL;    // Prevent the appearance of wild pointer
        }
        cout << "Person Destructor call" << endl;
    }

    int m_age;
    int *m_height;      //Use the new operator to open up data in the heap area, and use the pointer to receive the data
};

void test01()
{
    Person p1(10, 160);
    cout << "p1 Your age is: " << p1.m_age << " p1 Your weight is: " << *p1.m_height << endl;    //Receive the return value of the heap with a pointer

    Person p2(p1);
    cout << "p1 Your age is: " << p1.m_age << " p1 Your weight is: " << *p1.m_height << endl;
}

int main() {

    test01();

    system("pause");
    return 0;
}


=====Initialization list=====
Function: c + + provides initialization list syntax to initialize attributes < br >
Syntax: constructor (): attribute 1 (value 1), attribute 2 (value 2)... {} < br >

//
#include<iostream>
using namespace std;

class Person {

public:
    
    //Initialization list initialization properties
    Person(int a,int b,int c) :m_A(a), m_B(b), m_C(c)
    {

    }


    
    int m_A;
    int m_B;
    int m_C;
};

void test01()
{
    Person p(10,20,30);
    cout << "A Is: " << p.m_A<<endl;
    cout << "B Is: " << p.m_B << endl;
    cout << "C Is: " << p.m_C << endl;
}

int main() {

    system("pause");
    return 0;
}


=====c + + object model and this pointer=====
Member variables and member functions are stored separately < br >
In c + +, member variables and member functions in a class are stored separately < br >
Only non static member variables belong to class objects < br >
The c + + compiler will also allocate a byte space to each empty object to distinguish the memory occupied by empty objects. Each empty object should also have a unique memory address < br >
======this pointer concept======
Member variables and member pointers are stored separately, and the differentiated call of this piece of code is completed through this pointer. This pointer points to the object to which the called member function belongs < br >
this pointer is a pointer implied in each non static member function < br >
this pointer does not need to be defined and can be used directly < br >
The use of this pointer: when a formal parameter has the same name as a member variable, it can be distinguished by this pointer; Return the object itself in the non static member function of the class. You can use return * this < br >

//this pointer can be used in two cases
#include<iostream>
using namespace std;
class Person {

public:
    Person(int age)
    {
        this->age = age;    //The this pointer points to the object to which the called member function belongs
    }

    Person& PersonAddAge(Person p)
    {
        this->age += p.age;
        return *this;   //This points to the pointer to p2, and * this points to the object ontology p2
    }
    int age;
};

//1. Resolve name conflicts
void test1()
{
    Person p1(18);
    std::cout << "p1 Age: " << p1.age << std::endl;
}

//2. Return the object itself with * this
void test2()
{
    Person p1(5);
    Person p2(3);
    p2.PersonAddAge(p1).PersonAddAge(p1).PersonAddAge(p1);
    cout << "p2 Age: " <<p2.age<< endl;
}

int main() {

    test1();

    test2();

    system("pause");
    return 0;
}


=====Calling a member function with a null pointer=====
c + + hollow pointers can also call member functions, but pay attention to whether this pointer is used < br >
If this pointer is used, it needs to be judged to ensure the robustness of the code < br >
=====const modifier member function=====
Constant function: < br >
After adding const to a member function, we call this function a constant function < br >
Member attributes cannot be modified in constant functions < br >
After the keyword mutable is added to the member attribute declaration, it can still be modified in the constant function < br >
Constant object: < br >
Add const before declaring an object to call it a constant object < br >
Constant objects can only call constant functions < br >
=====Friends=====
The purpose of a friend is to let a function or class access private members in another class < br >
Friend < br >
Three implementations of friends: global functions as friends     Class as friend   Member functions are friends < br >

//friend    Write before writing member variables and member functions in a class
#include<iostream>
using namespace std;

class Building {
    
    friend void person1(Building* building);
public:
    Building()
    {
        m_SittingRoom = "a living room";
        m_BedRoom = "bedroom";
    }
    string m_SittingRoom;
private:
    string m_BedRoom;
};

void person1(Building *building)
{
    cout << "A person is visiting  " << building->m_SittingRoom << endl;
    cout << "A person is visiting  " << building->m_BedRoom << endl;
}

void test1() {
    Building building;
    person1(&building);
}

int main() {

    test1();

    system("pause");
    return 0;
}


=====Inherit=====

//Basic syntax of inheritance
#include<iostream>
using namespace std;

class BasePage
{
public:
    void header()
    {
        cout << "Home page, open class" << endl;
    }
    void footer()
    {
        cout << "Help center, communication and cooperation" << endl;
    }
    void left()
    {
        cout << "Learning content" << endl;
    }
};

//Basic syntax of inheritance
class Java : public BasePage   //Jave page
{
public:
    void content()
    {
        cout << "Java Subject video" << endl;
    }
};

//Python page
class Python : public BasePage
{
public:
    void content()
    {
        cout << "Python Learning video" << endl;
    }
};

//c + + page
class Cpp: public BasePage
{
public:
    void content()
    {
        cout << "c++Learning materials" << endl;
    }
};

void test01()
{
    cout << "Java The page is as follows " << endl;
    Java ja;
    ja.header();
    ja.content();
    ja.left();
    ja.footer();
    cout << "--------------" << endl;
}
void test02()
{
    cout << "Python The page is as follows " << endl;
    Python py;
    py.header();
    py.content();
    py.left();
    py.footer();
    cout << "--------------" << endl;
}
void test03()
{
    cout << "c++The page is as follows " << endl;
    Cpp cpp;
    cpp.header();
    cpp.content();
    cpp.left();
    cpp.footer();
    cout << "--------------" << endl;
}
int main() {

    test01();
    test02();
    test03();

    system("pause");
    return 0;

}


=====Inheritance mode=====
Inheritance syntax: class subclass: inheritance method   Parent class < br >
There are three ways of inheritance: public inheritance   Protect inheritance   Private inheritance < br >
<gallery>
Differences in inheritance.jpg
</gallery>
A child class is also called a derived class, and a parent class is also called a base class < br >
The private members in the parent class cannot be accessed in the child class, but the private members are only hidden and will be inherited < br >
=====Object model in inheritance=====
All non static member attributes in the parent class will be inherited by the child class < br >
The private member attribute in the parent class is hidden by the compiler, so it is inaccessible, but it is indeed inherited < br >
=====Construction and deconstruction order in inheritance=====
First construct the parent class, and then construct the child class; The order of destructions is just opposite to that of structures < br >
=====Inherit the handling of members with the same name=====
You can access members with the same name in a subclass directly < br >
To access a member with the same name as the parent class, you need to add a scope (::   Double colons) < br >

//The function with the same name is processed, and the scope needs to be added when accessing the member with the same name of the parent class
#include<iostream>
using namespace std;

class Base
{
public:
    Base()
    {
        m_A = 100;
    }
    int m_A;
    void func(int a)
    {
        cout << "Base  func call" << endl;
    }
};

class Son : public Base
{
public:
    Son() {
        m_A = 200;
    }
    int m_A;
    void func()
    {
        cout << "Son  func call" << endl;
    }
};
//How member properties with the same name are handled
void test01()
{
    Son s;
    cout << "Son lower m_A = " << s.m_A << endl;
    cout << "Base lower m_A = " << s.Base::m_A << endl;     //If you access a member with the same name in the parent class through a subclass object, you need to add a scope
}
//Member function processing with the same name
void teat02()
{
    Son s;
    s.func();   //Directly call, which is a member with the same name in a subclass
    /*s.Base::func(); */    // Add scope calls a function with the same name in the parent class

    //If a member function with the same name as the parent class appears in the subclass, the member with the same name in the subclass will hide all member functions with the same name in the parent class
    //If you want to access a member function with the same name hidden in the parent class, you need to add a scope
    s.Base::func(100);
}

int main()
{
    test01();

    system("pause");
    return 0;
}


=====Handling of static members with the same name in inheritance=====
You can access members with the same name in a subclass directly < br >
To access a member with the same name as the parent class, you need to add a scope < br >
=====Multiple inheritance syntax=====
c + + allows a class to inherit multiple classes < br >
Syntax: class subclass: inheritance method parent class 1, inheritance method parent class 2,...... < br >
Multiple inheritance may cause members with the same name to appear in the parent class, which needs to be differentiated by scope < br >
Multi inheritance is not recommended in c + + development < br >
=====Diamond inheritance (diamond inheritance)=====
Concept of diamond inheritance: < br >
Two derived classes inherit the same base class < br >
Another class inherits two derived classes at the same time < br >

//diamond inheritance 
#include<iostream>
using namespace std;

class Animal 
{
public:
    int m_Age;
};
//Using virtual inheritance to solve the problem of diamond inheritance
//Add the keyword before inheritance, and virtual becomes virtual inheritance
//The Animal class is called a virtual base class
class Sheep : virtual public Animal{};
class Tuo : virtual public Animal{};
class SheepTuo : public Sheep,public Tuo{};

void test1()
{
    SheepTuo st;
    //When the diamond inherits,; Two parent classes have the same data and need to be scoped
    st.Sheep::m_Age = 10;
    st.Tuo::m_Age = 12;
    cout << "Age of sheep " << st.Sheep::m_Age << endl;
    cout << "Tuo's age " << st.Tuo::m_Age << endl;
}

int main()
{
    test1();
    system("pause");
    return 0;
}


=====Polymorphism=====
Static polymorphism: function overloading and operator overloading belong to static polymorphism and reuse function names < br >
Dynamic polymorphism: polymorphism in the implementation of derived classes and virtual functions (the virtual keyword is added before the function to become a virtual function) < br >
The difference between static polymorphism and dynamic polymorphism: 1. The function address of static polymorphism is early bound - the function address is determined in the compilation stage   2. Dynamically polymorphic function address late binding - function address determined at run time < br >
Polymorphism meets the following conditions: 1. There is an inheritance relationship. 2. The subclass overrides the virtual function in the parent class < br >
Polymorphic usage conditions: 1. The parent class pointer or reference points to the child class object < br >
Rewriting: the function return value type is completely consistent with the function name parameter list, which is called rewriting < br >

//Basic syntax of polymorphism
#include<iostream>
using namespace std;

class Animal
{
public:
    virtual void speak()     //Virtual function     The dynamic polymorphism is realized by constructing virtual functions, and then the late binding of addresses is realized
    {
        cout << "Animals are talking" << endl;
    }
};

class Cat : public Animal
{
public:
    void speak()
    {
        cout << "The kitten is talking" << endl;
    }
};

class Dog : public Animal
{
public:
    void speak() 
    {
        cout << "The dog is talking" << endl;
    }
};

void doSpeak(Animal &animal)     //Address early binding   The function address is determined at the compilation stage. If you want to let the cat talk, the address of this function cannot be bound in advance. It needs to be bound in the run stage, and the address is bound late
{
    animal.speak();
}

void test1()
{
    Cat cat;
    doSpeak(cat);

    Dog dog;
    doSpeak(dog);
}
int main()
{
    test1();

    system("pause");
    return 0;
}


======Pure virtual functions and abstract classes======
The virtual functions in the parent class have no practical significance, so the virtual functions in the parent class are changed to pure virtual functions < br >
Pure virtual function syntax: virtual return value type function name (parameter list) = 0< br>
When there are pure virtual functions in a class, this class is also called an abstract class < br >
Abstract class features: 1. Objects cannot be instantiated. 2. Subclasses must rewrite pure virtual functions in abstract classes, otherwise they also belong to abstract classes < br >
For example, a member function in the parent class is virtual void func() = 0;   If there is a pure virtual function in the parent class, the pure virtual function in the abstract class must be overridden in the child class, that is, virtual void func()   {....}<br>
======Virtual destruct and pure virtual destruct======
When polymorphism is used, if an attribute in a subclass is opened to the heap, the parent class pointer cannot call the destructor code of the subclass when it is released < br >
Solution: change the destructor in the parent class to virtual destructor or pure virtual destructor < br >
Virtual destructor and pure virtual destructor have the following commonalities: 1. It can release subclass objects from parent class pointers; 2. Both require specific function implementations < br >
Difference between virtual destruct and pure virtual destruct: if it is pure virtual fiction, this class belongs to abstract class and cannot instantiate object < br >

//Virtual destruct and pure virtual destruct
#include<iostream>
using namespace std;
#include<string>

class Animal
{
public:
    virtual void speak() = 0;
    Animal()
    {
        cout << "animal Constructor call for" << endl;
    }
    virtual ~Animal()      //Using virtual destructor to solve the problem of unclean release in reactor area
    {
        cout << "animal Destructor call for" << endl;
    }
};

class Dog : public Animal
{
public:
    Dog(string name)
    {
        cout << "dog Constructor call for" << endl;
        m_Name = new string(name);
    }
    virtual void speak()
    {
        cout <<*m_Name<< "The dog is talking" << endl;
    }
    ~Dog()
    {
        cout << "dog Destructor call for" << endl;
        if (m_Name != NULL)
        {
            delete m_Name;
            m_Name = NULL;
        }
    }
    string *m_Name;
};

void test2()
{
    Animal* animal = new Dog("Tim");
    animal->speak();
    //When the parent class pointer is destructed, it will not call the destructor in the subclass, resulting in memory leakage if the subclass has heap attributes
    delete animal;
}

int main()
{
    test2();
    system("pause");
    return 0;
}


Virtual destructor: add virtual < br > before the parent destructor
Pure virtual destructor: in the parent class, change the virtual destructor = 0 to pure virtual destructor< br>
Pure virtual destructors need to be declared in the parent class and implemented in detail < br >
For example, the parent class is < br >
class Animal{
public:
          virtual ~Animal() = 0;      // Pure virtual deconstruction
};
//Concrete implementation
Animal::~Animal()
{
      Cout < < call of animal pure virtual destructor < < endl;
}
=====File operation=====
The data generated when the program runs belongs to temporary data, which will be released once the program runs < br >
Data can be persisted through files < br >
File operations in c + + need to include header files < fstream > < br >
There are two types of files: < br >
1. Text file: the file is stored in the computer in the form of ASCII code of text < br >
2. Binary files: files are stored in the computer in binary form of text, and users generally cannot read them directly < br >
Three categories of operation files: 1. ofstream: write operation (o for output)   2. ifstream: read operation (i stands for input)   3. fstream: read / write operations < br >
======Text file======
=======Write file=======
1. Include header file     # include<fstream><br>
2. Create flow object     ofstream   ofs;< br>
3. Open file       ofs.open("file path", opening method)< br>
4. Write data         Ofs < < "written data"< br>
5. Close file       ofs.close();< br>
File opening method < br >
ios::in           Open a file for reading < br >
ios::out         Open file for writing < br >
ios::ate         Initial location: end of file < br >
ios::app         Write file in append mode < br >
ios::trunc       If the file exists, delete it before creating it < br >
ios::binary       Binary mode < br >
Note: the file opening method can be used in conjunction with the | operator < br >

//Text file   Write file
#include<iostream>
using namespace std;
#include<fstream>
//Text file   Write file
void test01()
{
    //1. Include header file fstream

    //2. Create flow object
    ofstream ofs;
    //3. Open file
    ofs.open("test.txt", ios::out);
        //4. Write data
        ofs << "Name: Zhang San" << endl;
        ofs << "Gender: Male" << endl;
    //5. Close the file
        ofs.close();

}

int main()
{

    test01();
    system("pause");
    return 0;
}


Summary: < br >
1. File operation must include header file fstream < br >
2. You can use ofstream or fsstream < br > to write files
3. When opening a file, you need to operate the file path and the opening method < br >
4. You can write data to a file using < < br >
5. After the operation, close the file < br > ========= read the file=======
1. Include header file     # include<fstream><br>
2. Create flow object     ifstream   ifs;< br>
3. Open the file and judge whether the opening is successful   ifs.open("file path", opening method)< br>
4. Read data       Four ways to read < br >
5. Close file       ifs.close();< br>

///Text file read file
#include<iostream>
#include<fstream>
using namespace std;
#include<string>

//Text file read file
void test02()
{
    //1. Include header file
    //2. Create flow object
    ifstream ifs;
    //3. Open the file and judge whether the file is opened successfully
    ifs.open("test.txt", ios::in);
    if (!ifs.is_open())
    {
        cout << "File open failed" << endl;
        return;
    }
    //4. Read file
    //4.1 the first method is to read documents
    char buf[1024] = { 0 };
    while (ifs >> buf)
    {
        cout << buf << endl;
    }
    //4.2 the second method is to read documents
    char buf[1024] = { 0 };
    while (ifs.getline(buf,sizeof(buf)))
    {
        cout << buf << endl;
    }
    //4.3 the third way to read documents
    string buf;
    while (getline(ifs, buf))             //getline means to get a row and write a row in ifs to buf
    {
        cout << buf << endl;
    }
    //4.4 the fourth way to read documents
    char c;
    while ((c = ifs.get()) != EOF)      //EOF : end of file
    {
        cout << c;
    }
    //5. Close file
    ifs.close();
}

int main()
{

    test02();
    system("pause");
    return 0;
}


Summary: < br >
1. ifstream or fsstream < br > can be used to read files
2. Using is_ The open function can judge whether the file is opened successfully < br >
3. Close close file < br >
======Binary file======
Read and write files in binary mode < br >
The opening method should be IOS:: binary < br >
=======Write file=======
Writing files in binary mode mainly uses the stream object to call the member function write < br >
Function prototype: ostream & write (const char * buffer, int len)< br>
Parameter explanation: the character pointer buffer points to a storage space in the memory, and len is the number of bytes read and written < br >

//Binary file   Write file
#include<iostream>
#include<fstream>
using namespace std;

class Person
{
public:
    char m_Name[64];
    int m_Age;
};

void test1()
{
    ofstream ofs;
    ofs.open("person.txt", ios::binary | ios::out);

    Person p = { "Zhang San",18 };
    ofs.write((const char*)&p, sizeof(Person));
    ofs.close();
}

int main()
{

    test1();
    system("pause");
    return 0;
}


=======Read file=======
Binary file reading mainly uses stream object to call member function read < br >
Function prototype: istream & read (char * buffer, int len)< br>
Parameter explanation: the character pointer buffer points to a storage space in the memory, and len is the number of bytes read and written < br >

//Binary file   read file
#include<iostream>
#include<fstream>
using namespace std;

class Person
{
public:
    char m_Name[64];
    int m_Age;
};

void test2()
{
    ifstream ifs;
    ifs.open("Person.txt", ios::binary|ios::in);
    if (!ifs.is_open())
    {
        cout << "File open failed" << endl;
    }
    Person p;
    ifs.read((char*)&p, sizeof(Person));
    ifs.close();
}
int main()
{

    test2();
    system("pause");
    return 0;
}
</source >
</pre>
=====vector The container holds custom data types=====
</pre> 
<source lang="cpp" >
//=The vector container holds custom data types
#include<iostream>
using namespace std;
#include<vector>

class Person
{
public:

    Person(string name, int age)
    {
        this->m_Name = name; this->m_Age = age;
    }
    string m_Name;
    int m_Age;
};

void test1()
{
    /*vector<Person>v;
    Person p1("Zhang San ", 19);
    Person p2("Li Si ", 56);
    Person p3("Wang Wu ", 49);
    Person p4("Zhao Liu ", 29);*/
    //v.push_back(p1);
    Add data to container
    //v.push_back(p2);
    //v.push_back(p3);
    //v.push_back(p4);
    //Traverse the data in the container
    for (vector<Person>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << "full name:" << (*it).m_Name << "  Age:" << (*it).m_Age << endl;     //It is equivalent to a pointer pointing to the data type in < >, * it is the dereference operation, and the Person data type is solved
    //Dereference the Person attribute, or the IT pointer can point to the Person attribute, that is, it - > M_ Age
    }
}

//A pointer to a custom data type is stored in the vector container
void test2()
{
    vector<Person*> v;
    Person p1("Zhang San", 19);
    Person p2("Li Si", 56);
    Person p3("Wang Wu", 49);
    Person p4("Zhao Liu", 29);
    v.push_back(&p1);
    v.push_back(&p2);
    v.push_back(&p3);
    v.push_back(&p4);
    for (vector<Person*>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << "full name: " << (*it)->m_Name << " Age: " << (*it)->m_Age << endl;
    }
}

int main()
{
    test2();

    system("pause");
    return 0;
}


=====vector container nested container=====

//
#include<iostream>
using namespace std;
#include<vector>

//Container nested container
void test3()
{
    vector<vector<int>> v;
    //Create a small container
    vector<int> v1;
    vector<int> v2;
    vector<int> v3;
    vector<int> v4;
    //Drop data into small containers
    for (int i = 0; i < 4; i++)
    {
        v1.push_back(i + 1);
        v1.push_back(i + 2);
        v1.push_back(i + 3);
        v1.push_back(i + 4);
    }
    //Insert the small container into the large container
    v.push_back(v1);
    v.push_back(v2);
    v.push_back(v3);
    v.push_back(v4);
    //Through the large container, traverse all the data
    for (vector<vector<int>>::iterator it = v.begin(); it != v.end(); it++)
    {
        //(*it)    Is the small container vector < int >
        for (vector<int>::iterator vit = (*it).begin(); vit != (*it).end(); vit++)
        {
            cout << *vit << " ";
        }
        cout << endl;
    }
}

int main()
{
    test3();

    system("pause");
    return 0;
}


=====string=====
Essence: string is a c + + style string, and string is essentially a class < br >
The difference between string and char *: char * is a pointer; String is a class. Char * is encapsulated inside the class. It manages this string. It is a char * container < br >
Features: string class encapsulates many member methods. For example: find, copy, delete, replace, insert; string manages the memory allocated by char * without worrying about assignment out of bounds and address out of bounds. It is carried out within the class < br >
=====string constructor=====
Constructor prototype: < br >
string();                               // Create an empty string, for example: string str< br>
string(const char* s);          // Initialize with string s < br >
string(const string& str);    // Initialize another string object with one string object < br >
string(int n,char c);            // Initialize with n characters C < br >

//
#include<iostream>
using namespace std;

void test01()
{
    string s1;   //Default constructor 
    const char* str = "hello world";   //c language style string type
    string s2(str);    //Parameterized constructor
    cout << "s2= "<<s2 << endl;
    string s3(s2);     //copy constructor 
    cout << "s3= " << s3 << endl;
    string s4(10,'a');
    cout << "s4= " << s4 << endl;
}

int main()
{
    test01();

    system("pause");
    return 0;
}


=====string assignment operation=====
Assigned function prototype < br >
string& operator=(const char* s);               // Char * type string is assigned to the current string < br >
string& operator=(const string &s);           // Assign the string s to the current string < br >
string& operator=(char c);                        // Assign characters to the current string < br >
string& assign(const char* s);                    // Assign the string s to the current string < br >
string& assign(const char* s,int n);            // Assign the first n characters of string s to the current string < br >
string& assign(const string &s);                // Assign the string s to the current string < br >
string& assign(int n,char c);                      // Assign n characters C to the current string < br >
=====String splicing=====

//String splicing   append (,) parameter 1 is the splicing content, and parameter 2 is the first few characters
#include<iostream>
using namespace std;

void test01()
{
    string str1 = "I";
    str1 += "Love scientific research";
    cout << "str1= " << str1 << endl;

    str1 += '!';
    cout << "str1= " << str1 << endl;

    string str2 = "UE c++";
    str1 += str2;
    cout << "str1= " << str1 << endl;
    
    string str3 = "I ";
    str3.append("love ");
    cout << "str3= " << str3 << endl;

    str3.append("ccc xxx sss", 4);    //Take the first four characters, and the space is also one character
    cout << "str3= " << str3 << endl;

    str3.append(str2);
    cout << "str3= " << str3 << endl;

    str3.append(str2, 0, 2);       //For splicing str2, parameter 1 is the spliced object, parameter 2 is the starting position of splicing interception, and parameter 3 is the number of characters intercepted
    cout << "str3= " << str3 << endl;
}

int main()
{
    test01();

    system("pause");
    return 0;
}


=====Finding and replacing strings=====

//String lookup
#include<iostream>
using namespace std;

//String lookup
void test1()
{
    string str1 = "lxkcxs";
    int pos = str1.find('c');
    if (pos == -1)
    {
        cout << "No content found" << endl;
    }
    else
    {
        cout << "Find relevant content pos= " << pos << endl;
    }

    int pos2 = str1.rfind('x');             //rfind is the last place where the query content appears
    cout << "pos2= " << pos2 << endl;
}
//String replacement
void test2()
{
    string str2 = "aaabbbccc";
    str2.replace(2, 2, "1111");           //Parameter 1 is the replacement start position, parameter 2 is the number of replacement characters, and parameter 3 is the content to be replaced, which will be replaced
    cout << "str2= " << str2 << endl;    
}

int main()
{
    test1();
    test2();

    system("pause");
    return 0;
}


=====String comparison=====
Function Description: comparison between strings < br >
Comparison method: string comparison is based on the ASCII code of characters < br >
=Return 0; > Return to 1< Return - 1 < br >
Function prototype: < br >
int compare(const string &s) const;        // Compare with string s < br >
int compare(const char *s) const;           // Compare with string s < br >

//String comparison
#include<iostream>
using namespace std;

void test()
{
    string str1 = "lxk";
    string str2 = "cxk";

    if (str1.compare(str2) == 0)
    {
        cout << "str1 be equal to str2" << endl;
    }
    else if (str1.compare(str2) > 0)
    {
        cout << "str1 greater than str2" << endl;
    }
    else if (str1.compare(str2) < 0)
    {
        cout << "str1 less than str2" << endl;
    }
}

int main()
{
    test();

    system("pause");
    return 0;
}


=====string character access=====
There are two ways to access a single character in a string < br >
char& operator[ ](int n);          // Get characters by [] method < br >
char& at(int n);                        // Get characters through the at method < br >

//String access
#include<iostream>
using namespace std;

void test()
{
    string str = "hello";

    //Single character access via []
    for (int i = 0; i < str.size(); i++)
    {
        cout << str[i] << " " << endl;
    }

    //Single character access via at mode
    for (int i = 0; i < str.size(); i++)
    {
        cout << str.at(i) << endl;
    }

    //Modify single character
    str[0] = 'x';
    str.at(1) = 'x';
}
int main()
{
    test();

    system("pause");
    return 0;
}


=====string insert and delete=====

//string insert and delete
#include<iostream>
using namespace std;

void test()
{
    string str = "hello";

    //insert
    str.insert(1, "111");    //Parameter 1 of the insert function is the insertion position and parameter 2 is the insertion content
    cout << "str= " << str << endl;

    //delete
    str.erase(1, 3);       //Parameter 1 of erase function is the deletion start position, and parameter 2 is the number of characters deleted
}

int main()
{
    test();

    system("pause");
    return 0;
}


=====string substring=====
Function Description: get the desired substring from the string < br >
Function prototype: string substr(int pos = 0,int n = npos) const;     // Returns a string of n characters starting with pos < br >

//string substring
include<iostream>
using namespace std;

void test()
{
    string str = "asdfgh";
    string subStr = str.substr(1, 3);            //Parameter 1 of substr function is the starting position of substring interception, and parameter 2 is the number of characters intercepted
    cout << "subStr= " << subStr << endl;
}

//Practical operation
void email()
{
    string email = "xk_li@bupt.edu.cn";
    int pos = email.find('@');
    string Name = email.substr(0, pos);
    cout << "The owner of the mailbox is " << Name << endl;
}

int main()
{
    test();
    email();

    system("pause");
    return 0;
}


=====vector container=====
Basic concept of vector < br >
Function: vector data structure is very similar to array, also known as single ended array < br >
The difference between vector and ordinary array is that the array is a static space, while vector can be dynamically extended < br >
Dynamic expansion: instead of connecting a new space after the original space, find a larger memory space, and then copy the original data to a new space to free the original space < br >
======vector constructor======
Function prototype: < br >
vector<T> v;                               // The default constructor is implemented by the template implementation class < br >
vector(v.begin( ), v.end( ) );             // Copy the elements in the v[begin(),end()) interval to itself < br >
vector(n, elem);                          // The constructor copies n elems to itself < br >
vector(const vector &vec);                // Copy constructor < br >

//vector container constructor
#include<iostream>
using namespace std;
#include<vector>

void printVector(vector<int> &v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " " ;
    }
    cout << endl;
}

void test01()
{
    vector<int> v1;    //Default construction   Nonparametric structure
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }

    vector<int> v2(v1.begin(), v1.end());   //It is constructed by interval
    vector<int> v3(10, 100);     //n elem ents are constructed. Parameter 1 is the insert content and parameter 2 is the number
    vector<int> v4(v3);         //copy constructor 
    printVector(v1);
    printVector(v2);
    printVector(v3);
    printVector(v4);
}

int main()
{
    test01();

    system("pause");
    return 0;
}


======vector assignment operation======
Assign a value to the vector container < br >
Function prototype < br >
vector& operator=( const vector &vec);     // Overload the equal sign operator < br >
assign(beg,end);                           // Assign the data copy in the [beg, end) interval to itself < br >
assign(n,elem);                           // Copy n elems to itself < br >

//vector container assignment operation
#include<iostream>
using namespace std;
#include<vector>

void printVector(vector<int>& v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{
    vector<int> v1;    //Default construction   Nonparametric structure
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i);
    }
    printVector(v1);

    //Direct equal sign assignment
    vector<int> v2;
    v2 = v1;
    printVector(v2);

    //assign
    vector<int> v3;
    v3.assign(v1.begin(), v1.end());
    printVector(v3);

    //n elem ent assignment
    vector<int> v4;
    v4.assign(10, 100);
    printVector(v4);
}

int main()
{
    test01();

    system("pause");
    return 0;
}


======vector capacity and size======
Function prototype < br >
empty();                         // Judge whether the container is empty < br >  
capacity();                      // Container capacity < br >
size();                         // Returns the number of elements in the container < br >
resize(int num);               // Redefine the length of the container to num. if the container becomes longer, fill the new position with the default value of 0; if the container becomes shorter, the elements beyond the length of the container at the end will be deleted < br >
resize(int num,elem);          // Reformulate the length of the container to num. if the container becomes longer, fill the new position with elem value; If the container becomes shorter, the element whose end exceeds the length of the container is deleted < br >
======Insertion and deletion of vector======
Function prototype: < br >
push_back(ele);                                                         // Tail insertion ele < br >
pop_back();                                                             // Delete the last element < br >
insert(const_iterator pos,ele);                                         // The iterator points to the position POS to insert the element ele < br >
insert(const_iterator pos,int count,ele);                              // The iterator points to the position POS and inserts count elements ele < br >
erase(const_iterator pos);                                             // Delete iterator pointing element < br >
erase(const_iterator start,const_iterator end);                        // Delete the elements of the iterator from start to end < br >
clear();                                                                // Delete all elements in the container < br >
======vector data access======
Function prototype: < br >
at(int idx);         // Return the data indicated by the index idx < br >
operator[];         // Return the data indicated by the index idx < br >
front();            // Return the first data element in the container < br >
back();             // Return the last data element in the container < br >

//vector data access
#include<iostream>
using namespace std;
#include<vector>

void printVector(vector<int>&v)
{
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " " ;
    }
    cout << endl;
}

void test01()
{
    vector<int> v1;
    for (int i = 0; i < 10; i++)
    {
        v1.push_back(i + 2);
    }
    printVector(v1);

    //Accessing elements in an array in [] mode
    for (int j = 0; j < v1.size(); j++)
    {
        cout << v1[j] << " ";
    }
    cout << endl;

    //Accessing elements in at mode
    for (int k = 0; k < v1.size(); k++)
    {
        cout << v1.at(k) << " ";
    }
    cout << endl;

    //Get the first element
    cout << "The first element is:" << v1.front() << endl;
    //Get the last element
    cout << "The last element is:" << v1.back() << endl;
}

int main()
{
    test01();
    system("pause");
    return 0;


======vector interchange container======
Function prototype: < br >
swap(vec);           // Swap VEC with its own elements < br >
v1.swap(v2);            // Elements V1 and V2 are interchangeable < br >
Shrink memory with swap       vector<int>(v).swap(v); v
======vector reserved space======
Function Description: reduce the expansion times of vector during dynamic capacity expansion < br >
Function prototype:   reserve(int len);    // The container reserves len element lengths, the reserved positions are not initialized, and the elements are inaccessible < br >
=====deque container=====
:   Double ended array, you can insert and delete the head end < br >
The iterator of deque container also supports random access < br >
(the function interface is basically the same as the constructor of vector container) < br >
======deque constructor======  
Function prototype: < br >
deque<T>deqT;                        // Default construction form < br >
deque(beg,end);                      // The constructor copies the elements in the [beg, end] interval to itself < br >
deque(n,elem);                       // The constructor copies n elems to itself < br >
deque(const deque &deq);    // Copy constructor < br >
======deque assignment operation======
Function prototype: < br >
deque& operator=(const deque &deq);                      // Overload the equal sign operator < br >
assign(beg,end);                                         // Assign the data copy in the [beg, end] interval to itself < br >
assign(n,elem);                                          // Assign n elem copies to itself < br >

//deque constructor
#include<iostream>
using namespace std;
#include<deque>

void printDeque(const deque<int> &d)
{
    for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{
    deque<int> d1;

    for (int i = 0; i < 10; i++)
    {
        d1.push_back(i);
    }

    printDeque(d1);

    //Equal sign assignment
    deque<int> d2;
    d2 = d1;
    printDeque(d2);

    //assign assignment
    deque<int> d3;
    d3.assign(d1.begin(), d1.end());
    printDeque(d3);

    //n elem ent assignments
    deque<int> d4;
    d4.assign(10, 100);
    printDeque(d4);
}

int main()
{
    test01();

    system("pause");
    return 0;
}


======deque size operation======
Function prototype: < br >
deque.empty();                         // Determine whether the container is empty  < br>
deque.size();                          // Container capacity < br >
deque.resize(num);                     // Redefine the length of the container to num. if the container becomes longer, fill the new position with the default value of 0; If the container becomes shorter, the element whose end exceeds the length of the container is deleted < br >
deque.resize(num,elem);                // Reformulate the length of the container to num. if the container becomes longer, fill the new position with elem value; If the container becomes shorter, the element whose end exceeds the length of the container is deleted < br >
======deque insert and delete======
Function prototype: < br >
push_back(elem);         // Add a data at the end of the container < br >
push_front(elem);       // Insert a data in the container head < br >
pop_back();             // Delete the last data of the container < br >
pop_front();            // Delete the first data of the container < br >
Specify location operation:       < br>    
insert(pos,elem);              // Insert a copy of the element in the POS position and return the position of the new data < br >
insert(pos,n,elem);             // Insert n elem data in POS position, no return value < br >
insert(pos,beg,end);           // Insert the data in the [beg, end] interval at the POS position, and there is no return value < br >
clear();                       // Empty all data in the container < br >
erase(beg,end);               // Delete the data in the [beg, end] interval and return the position of the next data < br >
erase(pos);                   // Delete the data in POS position and return the position of the next data < br >
======deque data access======
Function prototype: < br >
at(int idx);       // Return the data indicated by the index idx < br >
operator[];        // Return the data indicated by the index idx < br >
front();           // Return the first data element in the container < br >
back();           // Return the last data element in the container < br >
======deque sort======
sort(d.begin(),d.end());   To use the algorithm sort, you need to include the algorithm header file   The default collation is ascending from small to large

//Sort sort
#include<iostream>
using namespace std;
#include<deque>
#include<algorithm>    // Standard algorithm header file

void printDeque(const deque<int>& d)
{
    for (deque<int>::const_iterator it = d.begin(); it != d.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test1()
{
    deque<int> d1;
    d1.push_back(10);
    d1.push_back(20);
    d1.push_back(30);
    d1.push_front(100);
    d1.push_front(300);
    d1.push_front(200);

    cout << "Before sorting: " << endl;
    printDeque(d1);

    cout << "After sorting: " << endl;
    sort(d1.begin(), d1.end());  //Sort   The default collation is ascending from small to large

}

int main()
{
    test1();

    system("pause");
    return 0;
}


====stack container=====
stack is a first in and last out data structure. It has only one exit < br >
Only the top elements in the stack can be used by the outside world, so the stack is not allowed to traverse < br >
The data entered in the stack is - push < br >
The pop-up data in the stack is - out of stack pop < br >
Can the stack judge whether the container is empty   empty()<br>
Can the stack return the number of elements?   sure   size()<br>
======stack common interface======
Constructor: < br >
stack<T> stk;                     // Stack is implemented by template class, and the default construction form of stack object < br >
stack(const stack &stk);          // Copy constructor < br >
Assignment operation: Stack & operator = (const Stack & STK);     // Overload the equal sign operator < br >
Data access: < br >
push(elem);         // Add an element to the top of the stack < br >
pop();              // Remove the first element from the top of the stack (out of the stack) < br >
top();              // Return stack top element < br >
Size operation: < br >
empty();      // Judge whether the stack is empty < br >
size();       // Return stack size < br >

//Use of common interfaces of stack container
#include<iostream>
using namespace std;
#include<stack>

void test01()
{
    stack<int> s;
    s.push(10);
    s.push(20);
    s.push(30);
    s.push(40);

    while (!s.empty())
    {
        cout << "The elements at the top of the stack are: " << s.top() << endl;   //View stack top element

        s.pop();    //Out of stack
    }

    cout <<"Stack size "<< s.size() << endl;
}

int main()
{
    test01();

    system("pause");
    return 0;
}


=====queue container=====
Concept: queue is a first in first out data structure with two exits < br >
Queue containers allow you to add elements from one end and remove elements from the other < br >
Only the head and tail of the queue can be used by the outside world, so the queue is not allowed to traverse < br >
Incoming data in the queue is called   Join the team push < br >
Queue outgoing data is called     Outgoing pop < br >
Only the head and tail of the queue can be accessed by the outside world, so traversal is not allowed < br >
======queue common interface======
Constructor: < br >
queue<T> que;                    // Queue is implemented by template class, and the default construction form of queue object < br >
queue(const queue &que);        // Copy constructor < br >
Assignment operation: < br >
queue& operator= (const queue &que);   // Overload the equal sign operator < br >
Data access: < br >
push(elem);   // Add elements to the end of the queue < br >
pop();        // Remove the first element from the team head < br >
back();       // Return the last element < br >
front();      // Return the first element < br >
Size operation: < br >
empty();      // Judge whether the stack is empty < br >
size();       // Return stack size < br >

//queue container common interface
#include<iostream>
using namespace std;
#include<queue>

class Person
{
public:
    Person(string name,int age)
    {
        this->m_Name = name;
        this->m_Age = age;
    }

    string m_Name;
    int m_Age;
};

void test01()
{
    queue<Person> q;

    Person p1("Zhang San", 30);
    Person p2("Li Si", 36);
    Person p3("Wang Wu", 22);
    Person p4("Zhao Liu", 20);

    q.push(p1);
    q.push(p2);
    q.push(p3);
    q.push(p4);

    while (!q.empty())
    {
        //View team header elements
        cout <<"Header data element------full name: " << q.front().m_Name <<" "<<"Age: "<<q.front().m_Age<< endl;

        //View tail element
        cout << "Tail data element-------full name: " << q.back().m_Name << " " << "Age: " << q.back().m_Age << endl;

        q.pop();
    }
    cout << "Queue size: " << q.size() << endl;
}

int main()
{
    test01();

    system("pause");
    return 0;
}

=====list container=====
Function: chain store data < br >
A linked list is a discontinuous storage structure on a physical storage unit. The logical order of data elements is realized through pointer links in the linked list < br >
A linked list is composed of a series of nodes < br >
Node composition: one is the data field for storing data elements, and the other is the pointer field for storing the next node < br >
Advantages: elements can be quickly inserted and deleted at any position < br >
Disadvantages: the traversal speed of the container is not as fast as that of the array, and the occupied space is larger than that of the array < br >
The linked list in STL is a two-way circular linked list < br >
======list constructor======

//list constructor
#include<iostream>
using namespace std;
#include<list>

void printList(const list<int>& L)
{
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test1()
{
    list<int>L1;     //Default construction
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);

    printList(L1);

    list<int> L2(L1.begin(), L1.end());
    printList(L2);

    list<int>L3(10, 100);
    printList(L3);

    list<int> L4(L3);
    printList(L4);
}

int main()
{
    test1();

    system("pause");
    return 0;
}


======list assignment and exchange======
Equal sign assignment < br >
assign function < br >
swap function < br >
< / PR assignment and swap operations

//type
#include<iostream>
using namespace std;
#include<list>

void printList(const list<int>& L)
{
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test1()
{
    list<int>L1;    
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);

    list<int>L2;
    L2 = L1;     //Equal sign assignment

    list<int>L3;
    L3.assign(L2.begin(), L2.end());

    list<int> L4;
    L4.assign(10,100);

    printList(L1);
    printList(L2);
    printList(L3);

    printList(L4);
}

void test2()
{
    list<int>L1;
    L1.push_back(10);
    L1.push_back(20);
    L1.push_back(30);
    L1.push_back(40);

    list<int> L2;
    L2.assign(10, 100);

    L1.swap(L2);

    printList(L1);
    printList(L2);
}

int main()
{
    test1();

    test2();

    system("pause");
    return 0;
}


======list size operation======
list.empty();                      // Determine whether the container is empty  < br>
list.size();                          // Container capacity < br >
list.resize(num);               // Redefine the length of the container to num. if the container becomes longer, fill the new position with the default value of 0; If the container becomes shorter, the element whose end exceeds the length of the container is deleted < br >
list.resize(num,elem);      // Reformulate the length of the container to num. if the container becomes longer, fill the new position with elem value; If the container becomes shorter, the element whose end exceeds the length of the container is deleted < br >
======list insert and delete======
push_back(elem);       // Add an element at the end of the container < br >
pop_back();               // Delete the last element in the container < br >
push_front();             // Insert an element at the beginning of the container < br >
pop_front();              // Remove an element from the beginning of the container < br >
insert(pos,elem);       // Insert a copy of the elem element at the POS position and return the position of the new data < br >
insert(pos,n,elem);    // Insert n elem data in POS position, no return value < br >
insert(pos,beg,end);   // Insert the data in the [beg, end] interval at the POS position, and there is no return value < br >
clear();                      // Remove all data from the container < br >
erase(beg,end);         // Delete the data in the [beg, end] interval and return the position of the next data < br >
erase(pos);             // Delete the data in POS position and return the position of the next data < br >
remove(elem);        // Delete all elements in the container that match the element value < br >
======list data access======
Function prototype: < br >
front();          // Return the first element < br >
back();          // Return the last element < br >
======list inversion and sorting======
Function prototype: < br >
reverse();    // Reverse linked list < br >
sort();        // Linked list sorting < br >

//list inversion and sorting
#include<iostream>
using namespace std;
#include<list>

void printList(const list<int>& L)
{
    for (list<int>::const_iterator it = L.begin(); it != L.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test01()
{
    //reversal
    list<int>L1;
    L1.push_back(20);
    L1.push_back(5);
    L1.push_back(55);
    L1.push_back(40);
    cout << "Before reversing:" << endl;
    printList(L1);

    L1.reverse();
    cout << "After reversal:" << endl;
    printList(L1);
}

bool myCompare(int v1,int v2)
{
    //In descending order, let the first number > the second number
    return v1 > v2;
}

void test02()
{
    //sort
    list<int>L1;
    L1.push_back(20);
    L1.push_back(5);
    L1.push_back(55);
    L1.push_back(40);
    cout << "Before sorting:" << endl;
    printList(L1);

    /*
    All containers that do not support random access iterators cannot use standard algorithms
    Containers that do not support random access iterators will provide corresponding algorithms internally
    */
    L1.sort();              //The default collation is from small to large   Ascending order
    cout << "After sorting:" << endl;
    printList(L1);

    L1.sort(myCompare);   //Descending operation
    printList(L1);
}

int main()
{
    test01();

    system("pause");
    return 0;
}


=====set/mutliset container=====
All elements are automatically sorted on insertion < br >
Essence: set/mutliset is an associative container, and the formation structure is realized by binary tree < br >
======The difference between set and mutliset======
set does not allow duplicate elements in the container < br >
mutliset allows duplicate elements in containers < br >
======Structure======
set<T> st;   // Default constructor < br >
set(const set &st);    // Copy constructor < br >
======Assignment======
set& operator=(const set &st);   // Overload the equal sign operator < br >
The only way to insert data is insert() < br >
======set size and swap======
size();                // Returns the number of elements in the container < br >
empty();           // Judge whether the container is empty < br >
swap(st);           // Swap two collection containers < br >
======set insert and delete======
Function prototype: < br >
insert(elem);        // Insert element in container < br >
clear();                // Clear all data < br >
erase(pos);          // Delete the element referred to by the POS iterator and return the iterator of the next element < br >
erase(beg,end);  // Delete all elements of the interval [beg, end] and return the iterator of the next element < br >
erase(elem);     // Delete the element with element in the container < br >
======set lookup and statistics======
Function prototype: < br >
find(key);   // Find out whether the key exists. If so, return the iterator of the key; If it does not exist, return set. End()< br>
count(key);     // Count the number of key elements < br >

//Search and statistics
#include<iostream>
using namespace std;
#include<set>

void printSet(set<int>& s)
{
    for (set<int>::iterator it = s.begin(); it != s.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

void test1()
{
    //lookup
    set<int> s1;
    s1.insert(20);
    s1.insert(30);
    s1.insert(10);
    s1.insert(50);

    printSet(s1);

    set<int>::iterator pos = s1.find(30);

    if (pos != s1.end())
    {
        cout << "Element found:" <<* pos << endl;
    }
    else {
        cout << "Element not found:" << *pos << endl;
    }
}

void test2()
{
    //Statistics
    set<int> s1;
    s1.insert(20);
    s1.insert(30);
    s1.insert(10);
    s1.insert(50);

    int num = s1.count(30);
    cout << "num= " << num << endl;
}

int main()
{
    test1();
    test2();

    system("pause");
    return 0;
}


======pair group creation======
Function Description: for paired data, two data can be returned by using the pair group < br >
There are two creation methods: < br >
pair<type,type> p (value1,value2);     <br>                
pair<type,type> p =make_pair(value1,value2);<br>

//pair group creation
#include<iostream>
using namespace std;

void test1()
{
    //The first way is to create a pair of groups
    pair<string, int>p("Tom", 22);
    

    //The second way is to create pairs of groups
    pair<string, int>p2 = make_pair("Tim", 33);
    cout << "full name:" << p2.first << " Age:" << p2.second << endl;
}

int main()
{
    test1();

    system("pause");
    return 0;
}


======set container sort======
Sorting rules can be changed by using affine functions < br >

//Store built-in data types
#include<iostream>
using namespace std;
#include<set>

void printSet(set<int>& s)
{
    for (set<int>::iterator it = s.begin(); it != s.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

class myCompare      //Create a class that returns true if one number is greater than another
{
public:
    bool operator()(int v1, int v2)   //functor 
    {
        return v1 > v2;
    }
};

void test1()
{
    set<int> s1;

    s1.insert(20);
    s1.insert(40);
    s1.insert(10);
    s1.insert(30);

    printSet(s1);

    set<int> s2;    //Specifies that the collation is from large to small

    s2.insert(20);
    s2.insert(40);
    s2.insert(10);
    s2.insert(30);

    for (set<int, myCompare>::iterator it = s2.begin(); it != s2.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

//Store custom data types
#include<iostream>
using namespace std;
#include<set>

class Person
{
public:
    Person(string name, int age)
    {
        this->m_Name = name;
        this->m_Age = age;
    }

    string m_Name;
    int m_Age;
};

class comparePerson
{
public:
    bool operator()(const Person& p1, const Person& p2)const
    {
        return p1.m_Age > p2.m_Age;
    }
};

void test1()
{

    //Custom data types specify collations
    set<Person,comparePerson>s;
    Person p1("Liu Bei", 25);
    Person p2("Guan Yu", 23);
    Person p3("Fei Zhang", 22);
    Person p4("Zhao Yun", 26);

    s.insert(p1);
    s.insert(p2);
    s.insert(p3);
    s.insert(p4);

    for (set<Person,comparePerson>::iterator it = s.begin(); it != s.end(); it++)
    {
        cout << "full name: " << it->m_Name << "  Age: " << it->m_Age <<endl ;
    }
}

int main()
{
    test1();

    system("pause");
    return 0;
}


=====map/mutlimap container=====
All elements in the map container are pair < br >
The first element in pair is key, which serves as an index, and the second element is value < br >
All elements are automatically sorted according to their key values < br >
map/mutlimap is an associative container, and its underlying structure is implemented by binary tree < br >
Advantages: you can quickly find the value value according to the key value < br >
======Difference between map and mutlimap:======
map does not allow duplicate key value elements in the container < br >
mutlimap allows duplicate key value elements < br >
======map construction and assignment======
Function prototype: < br >
Structure: < br >
map<T1,T2>map;          // Map default constructor < br >
map(const map &mp);  // Copy constructor < br >
Assignment: < br >
map& operator=(const map &mp);    // Overloaded symbol operators < br >

//map container construction and assignment
#include<iostream>
using namespace std;
#include<map>

void printMap(map<int,int> &m)
{
    for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
    {
        cout <<"key= "<< (*it).first << " value= "<<it->second<<endl;
    }
    cout << endl;
}

void test()
{
    map<int, int> m;

    m.insert(pair<int, int>(1, 10));
    m.insert(pair<int, int>(2, 20));
    m.insert(pair<int, int>(3, 30));
    m.insert(pair<int, int>(4, 40));

    printMap(m);

    map<int, int> m2(m);
    printMap(m2);

    map<int, int> m3;
    m3 = m2;
    printMap(m3);
}

int main()
{
    test();

    system("pause");
    return 0;
}


======map size and swap======
Function prototype: < br >
size();             // Returns the number of elements in the container < br >
empty();        // Judge whether the container is empty < br >
swap(mp);    // Swap two collection containers < br >
======map insert and delete======
Function prototype: < br >
insert(elem);            // Insert element in container < br >
clear();                 // Clear all elements < br >
erase(pos);             // Delete the element referred to by the POS iterator and return the iterator of the next element < br >
erase(beg,end);       // Delete all elements of the interval [beg, end] and return the iterator of the next element < br >
erase(key);            // Delete the element with key in the container < br >

//Insert and delete
#include<iostream>
using namespace std;
#include<map>

void printMap(map<int, int>& m)
{
    for (map<int, int>::iterator it = m.begin(); it != m.end(); it++)
    {
        cout << "key= " << (*it).first << " value= " << it->second << endl;
    }
    cout << endl;
}

void test01()
{
    map<int, int> m1;
    //Insert   First kind
    m1.insert(pair<int, int>(1, 10));

    //Insert second
    m1.insert(make_pair(2, 20));

    //Insert   Third
    m1.insert(map<int, int>::value_type(3, 30));

    //Insert   Fourth
    m1[4] = (40);
    printMap(m1);

    //delete
    m1.erase(m1.begin());
    m1.erase(3);
    m1.erase(m1.begin(), m1.end());
    m1.clear();
}

int main()
{
    test01();

    system("pause");
    return 0;
}


======map lookup and statistics======
Function prototype: < br >
find(key);            // Find out whether the key exists. If so, return the iterator of the element of the key; If it does not exist, return set. End()< br>
count(key);         // Count the number of key elements < br >

//Search and statistics
#include<iostream>
using namespace std;
#include<map>

void test01()
{
    map<int, int> m;
    m.insert(make_pair(1, 10));
    m.insert(make_pair(2, 20));
    m.insert(make_pair(3, 30));
    m.insert(make_pair(4, 40));

    map<int, int>::iterator pos = m.find(3);
    if (pos != m.end())
    {
        cout << "Element found key= " << pos->first << " value= " << pos->second << endl;
    }
    else {
        cout << " Element not found" << endl;
    }

    int num = m.count(2);
    cout << "num= " << num << endl;
}

int main()
{
    test01();

    system("pause");
    return 0;
}


======map sorting======
Sort from small to large by default < br >
Sorting rules can be changed by using affine functions < br >

//Sort   Sorting from large to small using imitation function
#include<iostream>
using namespace std;
#include<map>

class MyCompare
{
public:
    bool operator()(int v1, int v2)
    {
        return v1 > v2;
    }
};

void test()
{
    map<int, int,MyCompare> m;
    m.insert(make_pair(1, 10));
    m.insert(make_pair(2, 20));
    m.insert(make_pair(3, 30)); 
    m.insert(make_pair(4, 40));

    cout << "Before sorting" << endl;
    
    for (map<int, int, MyCompare>::iterator it = m.begin(); it != m.end(); it++)
    {
        cout << "key= " << (*it).first << " value= " << it->second << endl;
    }
    cout << endl;
    
}

int main()
{
    test();

    system("pause");
    return 0;
}


=====STL function object=====
Function object: a class that overloads the function call operator, and its object is called a function object; When a function object uses overloaded (), its behavior is similar to that of a function call, which is also called an imitation function < br >
Essence: a function object (functor) is a class, not a function < br >
Function object usage: < br >
Features: < br >
When a function object is used, it can be called like an ordinary function, with parameters and return values < br >
Function objects go beyond the concept of ordinary functions. Function objects have their own states < br >
Function objects can be passed as parameters < br >
=====Predicate=====
Functions that return bool types are called predicates < br >
If operator() accepts a parameter, it is called a unary predicate < br >

//The affine function returns bool type, and the parameter is 1, which is a unary predicate
#include<iostream>
using namespace std;
#include<vector>

class GeaterFive
{
public:
    bool operator()(int val)    //An imitation function that returns a boolean type is called a predicate, and a parameter is a unary predicate
    {
        return val > 5;
    }
};

void test01()
{
    vector<int>v;
    for (int i = 0; i < 10; i++)
    {
        v.push_back(i);
    }

    //Find in container   Is there a number greater than 5
    vector<int>::iterator it = find_if(v.begin(), v.end(), GeaterFive());   //Geeterfive() anonymous function object
    if (it == v.end())
    {
        cout << "not found" << endl;
    }
    else {
        cout << "A number greater than 5 was found" << *it << endl;
    }
}

int main()
{
    test01();

    system("pause");
    return 0;
}


If operator() accepts two arguments, it is called a binary predicate

//If the parameter of the functor is 2, it is a binary predicate
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>

class MyCompare
{
public:
    bool operator()(int val1, int val2)   //The two parameters are binary predicates
    {
        return val1 > val2;
    }
};

void test01()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);

    sort(v.begin(), v.end());
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;

    //Changing the algorithm strategy using function objects   Change to sort order from large to small
    sort(v.begin(), v.end(), MyCompare());
    for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
    {
        cout << *it << " ";
    }
    cout << endl;
}

int main()
{
    test01();

    system("pause");
    return 0;
}


=====Generic programming template=====
Template is to establish a general mold, which greatly improves the reusability < br >
Features of template: < br >
Templates cannot be used directly. They are just a framework < br >
The universality of templates is not omnipotent < br >
Another programming idea of c + + is called generic programming. The main technology used is template < br >
c + + provides two template mechanisms: function template and class template < br >
======Template syntax for function======
Function template function: create a general function whose function return value type and formal parameter type can be represented by a virtual type without specifying < br >
Syntax: < br >
template<typename T><br>
Function declaration or definition < br >
template  -- Claim to create template < br >
typename -- the symbol behind the surface is a data type, which can be replaced by class < br >
T  -- A common data type whose name can be replaced, usually in uppercase letters < br >
Precautions: < br >
For automatic type derivation, a consistent data type T must be derived before it can be used < br >
The template must determine the data type of T before it can be used < br >

//Function template
#include<iostream>
using namespace std;

//Function template
template<typename T>    //Declare a template. T is a general function template

void Swap(T& a, T& b)
{
    T temp = a;
    a = b;
    b = temp;
}

void test01()
{
    int a = 10;
    int b = 20;

    //Exchange using function templates
    //There are two ways to use function templates
    //1. Automatic type derivation  
    Swap(a, b);
    cout << "a=" << a << " b=" << b << endl;
    //2. Displays the specified type
    Swap<int>(a, b);
    cout << "a=" << a << " b=" << b << endl;
}

int main()
{
    test01();

    system("pause");
    return 0;
}


======Call rules for ordinary functions and function templates======
1. If both function templates and ordinary functions can be implemented, call ordinary functions first < br >
2. You can force the function template to be called through an empty template parameter list < br >
3. Function templates can also be overloaded < br >
4. If the function template can produce better matching, call the function template first < br >
======Class template======
Class template object as function parameter < br >
There are three types: < br >
1. Specifies the type of incoming  -- Directly display the data type of the object < br >
2. Parameter templating: change the parameters in the object into templates for transfer < br >
3. Whole class templating -- templating this object type for transfer < br >

//Class template
#include<iostream>
using namespace std;

template<class NameType,class AgeType>
class Person
{
public:
    Person(NameType name, AgeType age)
    {
        this->m_Name = name;
        this->m_Age = age;
    }

    void showPerson()
    {
        cout << "name: " << this->m_Name << " age: " << this->m_Age << endl;
    }

    NameType m_Name;
    AgeType m_Age;
};

void test01()
{
    Person<string,int> p1("Zhang San",22);
    p1.showPerson();
}

int main()
{
    test01();

    system("pause");
    return 0;
}


======Class template and inheritance======
When the parent class inherited by a subclass is a template, when declaring the subclass, specify the type of T in the parent class < br >
If not specified, the compiler cannot allocate memory to subclasses < br >
If you want to flexibly specify the type of T in the parent class, the child class also needs to be changed into a class template < br >
======Out of class implementation of class template member function======

//Out of class implementation of class template
#include<iostream>
#include<string>
using namespace std;

//Class template
template<class T1,class T2>
class Person
{
public:
    Person(T1 name, T2 age);

    void showPerson();

    T1 m_Name;
    T2 m_Age;
};

template<class T1, class T2>
void Person<T1, T2>::showPerson()
{
    cout << "full name:" << this->m_Name << " Age:" << this->m_Age << endl;
}

void test01()
{
    Person<string, int> p1("Zhang SA", 21);
    p1.showPerson();
}


int main()
{
    test01();

    system("pause");
    return 0;
}


======Sub file preparation of class template======
When writing sub files, it includes header file. h and source file. cpp. When calling standard library, include uses < >, and when calling self-defined library, include uses ""
<br>
 

Tags: C++ Back-end

Posted on Tue, 26 Oct 2021 02:49:14 -0400 by stuartc1