C + + tutorial (most complete)

1 Introduction to C + +

1.1 origin

-Bell Laboratories, 1980s (1979)

1.2 scope of application

  • Word processing programs and spreadsheets
  • compiler
  • operating system
  • Large scale games, etc

1.3 C + + and C

  • C language is a structured and modular language, process oriented.
  • C + + retains all the original advantages of C language and adds an object-oriented mechanism, commonly known as "C with classes", which was renamed C in 1983++

2 development tools

  • Notepad + + command line
  • Visual C++ 6.0: a classic development tool that conflicts with popular operating systems
  • VS 2015, etc.: powerful function and volume
  • Code::Blocks: an open source free development tool recommended by professional developers
  • Other development tools: DeV C + +, CLion, C-Free, Xcode, C4droid

3 basic grammar

  • Object - the behavior of an object that has a state. An object is an instance of a class.
  • Class - a class can be defined as a template for the behavior and state of an object.
  • Methods - basically, a method represents a behavior, and a class can contain multiple methods.
  • variable

3.1 notes

//Single-Line Comments 
/*
multiline comment 
multiline comment 
*/

3.2 keywords

asmelsenewthis
autoenumoperatorthrow
boolexplicitprivatetrue
breakexportprotectedtry
caseexternpublictypedef
catchfalseregistertypeid
charfloatreinterpret_casttypename
classforreturnunion
constfriendshortunsigned
const_castgotosignedusing
continueifsizeofvirtual
defaultinlinestaticvoid
deleteintstatic_castvolatile
dolongstructwchar_t
doublemutableswitchwhile
dynamic_castnamespacetemplate

3.3 identifier

  • An identifier is the name used to identify a variable, function, class, module, or any other user-defined item. An identifier starts with the letter A-Z or A-Z or underscore followed by zero or more letters, underscores, and numbers (0-9).
  • Punctuation characters such as @, & and% are not allowed in identifiers. C + + is a case sensitive programming language.

4 data type

4.1 basic data type

Seven basic C + + data types: bool, char, int, float, double, void, wchar_t
Type modifiers: signed, unsigned, short, long
Note: some basic types can be decorated with one or more type modifiers. For example, signed short int is abbreviated as short, and signed long int is abbreviated as long.

Type nameOccupied bytesNumerical range
void0
bool1{true.false}
wchar_t2 or 4 bytes
char(signed char)1-128~+127
short(signed short)2-32768~+32767
int(signed int)4-2147483648~+2147483647
long(signed long)4-2147483648~+2147483647
long long(signed long long)8-9,223,372,036,854,775,808 ~9,223,372,036,854,775,807
float4-.34*1038~3.4*1038
double8-1.7*10308~1.7*10308
unsigned char10~255
unsigned shrot20~65525
unsigned(unsigned int)40~4294967295
unsigned long40~4294967295
unsigned long long80 ~ 18,446,744,073,709,551,615
//x64 processor 64 bit windows10 vs2015 
#include <iostream>
using namespace std;
int main()
{
	bool b;
	char c;short s; int i; long l; long long ll; float f; double d; long double ld;long float lf;
	unsigned char uc; unsigned short us; unsigned int ui; unsigned long ul; unsigned long long ull;
	cout << sizeof(bool) <<  endl;
	cout << sizeof(char)<<" " << sizeof(short)<<" "<< sizeof(signed int) << " " << sizeof(long) << " " << sizeof(signed long long) << " " << sizeof(float) << " " << sizeof(double) << " " << sizeof(long float) << " " << sizeof(long double) << endl;
	cout <<sizeof(unsigned char)<<" "<< sizeof(unsigned short) << " " << sizeof(unsigned int) << " " << sizeof(unsigned long) << " " << sizeof(unsigned long long) << endl;
	cout << sizeof(unsigned) << endl;
	
	
	cout << "hello World!!!" <<endl;
	system("pause");
	return 0;
}

4.2 space occupied by data types in different systems

This is related to the machine, operating system and compiler. For example, in the 32bits operating system system, the int type takes up 4 bytes in VC + + compiler and 2 bytes in tuborC.
reason:

  • c/c + + specifies that the int word length is the same as the machine word length
  • The operating system word length may not be the same as the machine word length
  • The compiler defines the int word length based on the operating system word length
type16 bit operating system32-bit operating system64 bit operating system
char111
char*248
short222
int244
long448
long long888

Note: the occupation of long type in different compilers is different: in 32-bit, VC + + and GCC are 4 bytes; in 64 bit, VC + + is 4 bytes and GCC is 8 bytes.

4.3 typedef declaration

//Use typedef to give a new name to an existing type. The syntax is as follows:
typedef type newname
//eg: 
typedef int feet
feet distance

4.4 enumeration types

A derived data type in C + +, which is a collection of several enumeration constants defined by the user; the enumeration element is an integer type. The enumeration type can be implicitly converted to int type, and the int type cannot be implicitly converted to enumeration type.

//Syntax for ENUM types:
enum Enumeration name{
	identifier [=Integer constant], 
     identifier [=Integer constant], 
... 
    identifier [=Integer constant]
}Enumerating variables;

If the enumeration is not initialized, that is, when "= integer constant" is omitted, it starts from the first identifier;

  • By default, the value of the first name is 0, the value of the second name is 1, the value of the third name is 2, and so on. However, you can also assign a special value to the name, just add an initial value.
    For example:
enum course {math,chinese,english,physics,chemistry}c;
c = english;
cout<<c<<endl;  //2
//english is 1, physics is 2, chemistry is 3, chinese is still 1, math is still 0
enum course {math,chinese,english=1,physics,chemistry};

5 variables

In fact, variables are just the name of the storage area that can be operated by the program. Each variable in C + + has a specified type, which determines the size and layout of variable storage. The values within this range can be stored in memory, and operators can be applied to variables.

5.1 declaration and definition of variables

  • The variable declaration guarantees the compiler that the variable exists with the given type and name, so that the compiler can continue to compile further without knowing the full details of the variable.
  • You can declare a variable multiple times in a C + + program, but a variable can only be defined once in a file, function, or code block.
  • When multiple variables are assigned the same value, they need to be assigned separately.
int x = y = z = 66;//error
int x = 3,y = 3,z = 3;
int x, y ,z = 3;
x = y = z;

Variable declaration (no memory allocation): extern al data type variable name;
Definition of variables: data type, variable name 1, variable name 2,... Variable name n;

// Variable declaration
extern int a, b;
int main ()
{
  // Variable definition
  int a, b;
  // initialization
  a = 23;
  b = 25;
  return 0;
}

5.2 scope of variable

Local variables: variables declared inside a function or a code block are called local variables. They can only be used by statements inside functions or code blocks.
Global variables: variables defined outside all functions (usually at the head of the program) are called global variables. The value of a global variable is valid throughout the life cycle of the program.

  • The names of local variables and global variables can be the same, but within a function, the value of the local variable overrides the value of the global variable.
  • When a local variable is defined, the system will not initialize it; When defining a global variable, the system will automatically initialize the value: int float double 0, char '\ 0', pointer NULL
int i = 66;
int main ()
{
  int i = 88;
  cout << i<<endl;//8
  return 0;
}
float f;
double d;
char c;
int *p;
int main()
{
	cout << i << f << d << c << p << endl;//000 00000000
	return 0
}

6 operator

  • Arithmetic operators: + - * /% +--
  • Relational operator: = =! = < > =<=
  • Logical operator: & & |!
  • Bitwise operators: & ^ ~ < > >
  • Assignment operator: = + = - = * = / =% = < = > = & = ^ ==
  • Miscellaneous operators:
sizeof            //Returns the size of the variable. eg:sizeof(a) returns 4. A is the integer sizeof(int)
Condition?X:Y     //Ternary operator Condition is true, the value is X, otherwise the value is Y
,                //Comma expression, the value is the value of the last expression
.and->            //Members used to reference classes, structures, and utilities
Cast            //The castor eg:int(2.202) returns 2
&              //Pointer operator returns the address of the variable
*             //Pointer operator points to a variable
  • Operator priority
categoryoperatorAssociativity
suffix() [] -> . ++ - -From left to right
one yuan+ - ! ~ ++ - - (type)* & sizeofRight to left
Multiplication and division* / %From left to right
Addition and subtraction+ -From left to right
displacement<< >>From left to right
relationship< <= > >=From left to right
equal== !=From left to right
Bit AND and&From left to right
Bit exclusive or XOR^From left to right
Bit OR or|From left to right
Logic AND and&&From left to right
Logical OR|
condition?:Right to left
assignment= += -= *= /= %=>>= <<= &= ^==
comma,From left to right

7 grammatical structure

7.1 circulation structure

  • while
while(conditon)//0 is false, non-0 is true
{
	statement(s);
}
  • for
for(init;conditon;increment)//0 is false, non-0 or nothing is written as true
{
	statement(s);
}

1.init is executed first and will only be executed once, or no statement can be written.
2. Then judge condition, true to execute the loop body, and false to skip the loop
3. After executing the loop body, execute increment and skip to 2

int array[5] = { 11, 22, 33, 44, 55 };
for (int x : array)
{
	cout << x << " ";
}
cout << endl;
// auto type is also in the new C++11 standard, which is used to automatically obtain the type of variable
for (auto x : array)
{
	cout << x << " ";
}
  • for each
    for enhanced loop in STL.
int a[4] = { 4,3,2,1 };
for each (int var in a)
{
	cout << var << " ";
}

7.2 judgment structure

  • if
if(expr)
{
	statement;//If expr is true, the block of statements that will be executed 
}
if(expr)
{
   statement1;// If expr is true, the block of statements that will be executed
}
else
{
   statement2;// Statement to execute if expr is false
}
if(expr1)
{
   statement1;// If expr1 is true, the block of statements that will be executed
}
elseif(expr2)
{
   statement2;// If expr2 is true, the block of statements that will be executed
}
...
else
{
	statementElse;// Statement block executed when the above expressions are false
}
  • switch
switch(expression){
    case constant-expression  :
       statement(s);
       break; 
    case constant-expression  :
       statement(s);
       break; 
    // You can have any number of case statements
    default : // Optional
       statement(s);
}
  • The constant expression after each case must be different.
  • The order in which case statements and default statements appear has no effect on the execution results.
  • If there is no break after the case, no judgment will be made after the execution, and the next case statement will continue to be executed. Until I met brerak.
  • If there is no case after default, break can be omitted
  • Multiple case s can use a set of execution statements
char c = 'A';
	switch (c)
	{
	
	case 'A':
	case 'B':
	case 'C':
		cout << "Passed" << endl;
		break;
	default:
		cout << "fail," << endl;
	
	}

7.3 ternary operators

//If Exp1 is true, the value of Exp2 is calculated, and the result is the whole? The value of the expression. If Exp1 is false, the value of Exp3 is calculated, and the result is the whole? The value of the expression
Exp1 ? Exp2 : Exp3;

7.4 preprocessing command

Preprocessor (delete program comments, execute preprocessing commands, etc.) – > compiler compiles source program

  • Macro definition: #define identifier string
  • The file contains: #include < filename > or #include "filename"
  • Conditional compilation
//If the identifier is #define defined, execute segment 1, otherwise execute segment 2
#ifdef identifier
	Segment 1
#else
	Segment 2
#endif
//If the identifier has not been #define defined, execute segment 1, otherwise execute segment 2
#ifndef identifier
	Segment 1
#else
	Segment 2
#endif
//If the expression is true, execute segment 1, otherwise execute segment 2
#if expression
	Segment 1
#else
	Segment 2
#endif

8 array

Some data sets with the same data type or the same attribute (class) are identified by data name and distinguished by subscript or sequence number. The data in an array is called an element.

8.1 one dimensional array

Define the form of one-dimensional array: data type data name [constant expression]
Initialization form: data type array name [constant expression] = {initial value table};
Assign a value to an element of the array: array name [subscript] = value (subscript starts from 0)
Reference to array: array name [subscript]

  • When initializing an array, you can assign values to only some array elements
  • When assigning values to all element arrays, the length of the array can not be specified. The compiling system will determine the length of the array according to the number of initial values.
  • static array elements are not assigned initial values, and the system will automatically default to 0.
int arr1[4] = {1,2,3,4};
int arr2[4] = { 1,2 };
int arr[4] = {0];//All elements are 0
static int arr3[3];
int arr4[4];
cout << "arr1:"<<arr1[0] << arr1[1] << arr1[2] << arr1[3] << endl;
cout << "arr2:" << arr2[0] << arr2[1] << arr2[2] << arr2[3] << endl;
cout << "arr3:" << arr3[0] << arr3[1] << arr3[2] << arr3[3] << endl;
cout << "arr4:" << arr4[0] << arr4[1] << arr4[2] << arr4[3] << endl;

8.2 two dimensional array

Define the form of one-dimensional array: data type data name [constant expression 1] [constant expression 2]
Initialization form: data type array name [constant expression 1] [constant expression 2] = {initial value table};
Assign a value to an element of the array: array name [row subscript] [column subscript] = value (subscript starts from 0)
Array reference: array name [row subscript] [column subscript]

  • Write all data in a curly bracket and assign values automatically in the order of the number of array elements in memory
  • Some elements can be assigned values, and the values of other elements are automatically taken as 0
  • When defining an initialization array, the length of the first dimension can be omitted, and the second dimension cannot be saved. The system will automatically confirm the number of rows
int arr1[2][3];
int arr[2][3] = {0];//All elements are 0
int arr2[2][3] = { {1,2,3},{4,5,6} };
int arr3[2][3] = { 1,2,3 ,4,5,6 };
int arr4[2][3] = { {1},{4,6} };
int arr5[][3] = { 1,2,3 ,4,5,6 };

Character array
An array of char type can be regarded as a string when the last bit in the character array is' \ 0 '). The string class is defined in C + +, and the Cstring class is defined in Visual C + +.
Each character in the string occupies one byte, plus the last null character. For example:

//The string length is 8 bytes, and the last bit is' \ 0 '.
char array[10] = "yuanrui";//yuanrui\0\0\0
//You can also not define the string length, such as:
char arr[] = "yuanrui";//yuanrui\0

8.3 pointer to array

The concept of pointer will be explained in detail later.

double *p;
double arr[10];
p = arr;//p = &arr[0];
*(p+3);//arr[3]

8.4 array and new (dynamically create array)

One dimensional array:

int* arr1 = new int[2];//delete []arr1;
int* arr2 = new int[3]{ 1,2 };//delete []arr2

Two dimensional array

int m=2, n=3;
int** arr3 = new int*[2];//delete []arr3
for (int i = 0; i < 10; ++i)
{ 
	arr3[i] = new int[3]; // delete []arr3[i]
}
int* arr4 = new int[m*n];//Data is stored by row delete []arr3

8.5 arrays and functions

Array - > function

  • If you pass a two-dimensional array, the parameter must specify the length of the second dimension.
    The formal parameter is a pointer: void function(int *param)
    The formal parameter is an array of defined size: void function(int param[10])
    The formal parameter is an array of undefined size: void function(int param [])
    Two dimensional array: void function(int a[][3],int size)

Function returns an array

  • C + + does not support returning the address of a local variable outside a function unless the local variable is defined as a static variable.
int * function();
int** function();

8.6 get the size of the array

  • Cannot get array size for dynamically created (new) array of basic data types
int a[3];
//The first method
cout<<sizeof(a)/sizeof(a[0])<<endl;
//The second method
cout << end(a) - begin(a) << endl;
//Two dimensional array
int arr[5][3];
int lines = sizeof(arr) / sizeof(arr[0][0]);
int row = sizeof(arr) / sizeof(arr[0]);//that 's ok
int col = lines / row;//column
cout << row << "::"<<col << endl;
cout << end(arr) - begin(arr) << endl;//5 lines

9 function

Function is an important tool to realize the idea of modular programming. Every operation in C + + program is basically realized by a function. There can only be one main function in C + + program

9.1 function declaration and definition

  • Function type - the return value type of the function; Function name - must comply with C + + identifier naming rules, followed by a pair of parentheses; Function body - the subject part that implements the function; Argument list - in parentheses after the function name, used to pass or bring back values to the function.
  • In the function declaration, the parameter name can be omitted, and the parameter type and function type cannot be omitted.
  • The function declaration can be placed inside the calling function and before the calling statement; It can also be placed outside the main calling function. If it is before all the defined functions and the subsequent functions are defined in any order, each main calling function call does not need to be declared
  • When a function is defined before a function is called, the function declaration can be omitted.
    The last two are summarized as follows: before calling a function, the program must know that there is such a function, and the declaration is to let the program know that there is such a thing in advance
    Function declaration:
Function type function name(parameter list);
eg:
int max(int a,int b);//When declaring functions, a and B can be omitted
int max(int,int);
void show();

Function definition:

Function type function name(parameter list)
{
	Function body;
}
eg:
int max(int a,int b)
{
	int z;
	z = a>b?a:b;
	return z;
}

9.2 function parameters and return values

  • Formal parameters: the parameters in parentheses after the function definition do not occupy memory before the function call.
  • Arguments: parameters in parentheses of function call, which can be constants, variables or expressions.
    Formal parameters and arguments must have the same number, type and order
    Function transfer mode: value transfer, pointer, reference
         Pointers and references are described in detail later.
//Pass value - modifying the formal parameters in the function has no effect on the actual parameters
int add(int value)
{
	value++;
	return value;
}
int main()
{
	int v = 10;
	cout << "add() = " << add(v) << endl;//add() = 11
		cout << "v = " << v << endl;//v = 10
	return 0;
}
//Pointer - modifying formal parameters affects actual parameters
int add(int* pValue)
{
	(*pValue)++;
	return *pValue;
}
int main()
{
	int v = 10;
	cout << "add() = " << add(&v) << endl;//add() = 11
	cout << "v = " << v << endl;//v = 11
	return 0;
}
//Reference - modifying formal parameters affects actual parameters
int add(int &value)
{
	value++;
	return value;
}
int main()
{
	int v = 10;
	cout << "add() = " << add(v) << endl;//add() = 11
	cout << "v = " << v << endl;//v = 11
	return 0;
}

Functions with default parameters

int sum(int a, int b=2)
{
  return (a + b);
}
 
int main ()
{
   cout << "Total value is :" << sum(100, 200);<< endl;//Total value is :300
   cout << "Total value is :" << sum(100);<< endl;//Total value is :102
   return 0;
}

Return value of function

  • The return value is given through return. Return is followed by an expression, and only one value can be put back; If there is no expression, you can not write return; The parentheses after return are optional.
  • The expression type in the return statement should be consistent with the function type, otherwise the type will be automatically converted (the function type determines the return value type)

9.3 function call

  • Function can be used as a single statement. For the function with return value, the function call can be used as a part of the statement and the return value can be used to participate in the operation.
    Function call form: parameter passing – > function body execution – > return calling function
Function name(Argument list);
show();

Nested calls to functions:

int a()
{
	return 666;
}
int b(int sum)
{
	return sum+a()
}
int main()
{
	cout<<b(222)<<endl;//888
	return 0;
}

Recursive call of function: direct recursive call and indirect recursive call

  • A function directly or indirectly recursively calls the function itself, which is called the recursive call of the function
  • Recursion and regression: original problem = > subproblem solution of subproblem = > solution of original problem
//Direct recursive call: find the value of 1+...n
int total(int sum)
{
	if (sum == 1)
	{
		return 1;
	}
	return sum + total(sum - 1);
}
int main()
{
	cout << "total = " << total(10) << endl;//total = 55
	system("pause");
	return 0;
}
//Indirect recursive call
int f2();
int f1()
{
...
  f2()
}
int f2()
{
	f1();
}

9.4 function overloading

The same function name corresponds to different function implementations. Each type of implementation corresponds to a function body with the same name and function, but the type or number of parameters are different.
Multiple functions with the same name only have different function types (function return value types), and they are not overloaded functions

int add(int a,int b)
{
	return a+b;
}
double add(double a,double b)
{
	return a+b;
}
int add(int a,int b,int c)
{
	return a+b+c;
}

9.5 inline function

c + + can embed the called function code into the calling function when compiling. This function embedded in the calling function is called inline function, also known as embedded function or built-in function.

  • When defining an inline function, you can use inline in both the function definition and the function prototype declaration, or you can use it only in one place, which has the same effect.
  • The inline function is replaced by the function body of the inline function during compilation, so there is no function call, there is no need to protect the site, restore the site, and save the cost.
  • Inline functions increase the amount of code in the target program. Therefore, only functions with small scale and frequent use are generally declared as inline functions.
  • When the implementation of an inline function is too complex, the compiler will treat it as an ordinary function, so the inline function cannot contain loop statements and switch statements.
    The inline function format is as follows:
inline Function type function name(parameter list )
{
	Function body;
}
inline int add(int a, int b)
{
	return a + b;
}

9.6 insight into the underlying principles of inline functions

1. Use Visual Studio 2015 to create a C++Win32 console program, click Project - > project properties to set inline function optimization

2. Write inline function code, set breakpoints, and start debug

#include <iostream>
#include <string>
using namespace std;
inline int add(int a, int b)
{
	return a + b;//Breakpoint 1
}
int main()
{
	int result = add(12, 34);
	cout << result << endl;//Breakpoint 2
	return 0;
}

3. Debug - > window - > disassembly, and then you can see the compiled assembler

...
		int result = add(12, 34);
00B620DE  mov         eax,0Ch  
00B620E3  add         eax,22h  //Add the median value of eax and 22h and assign it to eax
00B620E6  mov         dword ptr [result],eax  
		cout << result << endl;
00B620E9  mov         esi,esp  
00B620EB  push        offset std::endl<char,std::char_traits<char> > (0B610A5h)  
00B620F0  mov         edi,esp  
00B620F2  mov         eax,dword ptr [result]  
00B620F5  push        eax  
00B620F6  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (0B6D098h)]  
00B620FC  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0B6D0A8h)]  
00B62102  cmp         edi,esp  
00B62104  call        __RTC_CheckEsp (0B611C7h)  
00B62109  mov         ecx,eax  
00B6210B  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0B6D0ACh)]  
00B62111  cmp         esi,esp  
00B62113  call        __RTC_CheckEsp (0B611C7h)   
		return 0;

4. From the assembly code, the inline function after code compilation can be directly embedded into the main function, and breakpoint 1 will not be executed. The following is the assembly code without inline function (excluding inline keyword):

int result = add(12, 34);
00291A4E  push        22h  
00291A50  push        0Ch  
00291A52  call        add (02914D8h)  //Call the add function
00291A57  add         esp,8//Move the stack pointer esp and continue to execute the main function
00291A5A  mov         dword ptr [result],eax  
		cout << result << endl;
00291A5D  mov         esi,esp  
00291A5F  push        offset std::endl<char,std::char_traits<char> > (02910A5h)  
00291A64  mov         edi,esp  
00291A66  mov         eax,dword ptr [result]  
00291A69  push        eax  
00291A6A  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (029D098h)]  
		cout << result << endl;
00291A70  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (029D0A8h)]  
00291A76  cmp         edi,esp  
00291A78  call        __RTC_CheckEsp (02911C7h)  
00291A7D  mov         ecx,eax  
00291A7F  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (029D0ACh)]  
00291A85  cmp         esi,esp  
00291A87  call        __RTC_CheckEsp (02911C7h)  
		system("pause");
00291A8C  mov         esi,esp  
00291A8E  push        offset string "pause" (0299B30h)  
00291A93  call        dword ptr [__imp__system (029D1DCh)]  
00291A99  add         esp,4  
00291A9C  cmp         esi,esp  
00291A9E  call        __RTC_CheckEsp (02911C7h)  
		return 0;

As you can see from the above code, the add function is called (call) in the main function.
5. After adding several loops to the inline function, the compiler treats the inline function as an ordinary function. The code is as follows:

inline int add(int a, int b)
{
	
	int sum = 0;
	for (int i = 0; i < 100; i++)
		a++;
	for (int i = 0; i < 100; i++)
	{
		
		for (int i = 0; i < 100; i++)
		{
			sum++;
		}
	}
	
	return a + b;
}
int main()
{
	int result = add(12, 34);
	cout << result << endl;
	return 0;
}
	int result = add(12, 34);
00181A4E  push        22h  
00181A50  push        0Ch  
00181A52  call        add (01814ECh)  ///
00181A57  add         esp,8  
00181A5A  mov         dword ptr [result],eax  
	cout << result << endl;
00181A5D  mov         esi,esp  
00181A5F  push        offset std::endl<char,std::char_traits<char> > (01810A5h)  
00181A64  mov         edi,esp  
00181A66  mov         eax,dword ptr [result]  
00181A69  push        eax  
00181A6A  mov         ecx,dword ptr [_imp_?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A (018D098h)]  
	cout << result << endl;
00181A70  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (018D0A8h)]  
00181A76  cmp         edi,esp  
00181A78  call        __RTC_CheckEsp (01811C7h)  
00181A7D  mov         ecx,eax  
00181A7F  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (018D0ACh)]  
00181A85  cmp         esi,esp  
00181A87  call        __RTC_CheckEsp (01811C7h)  
	return 0;
00181AA3  xor         eax,eax  

10 string

10.1 C-style string (character array)

A C-style string is actually a one-dimensional character array terminated with the null character '\ 0'.

  • The length of the input string must be less than the length of the defined character array, and the last bit is the / 0 termination symbol; Otherwise, the output cannot know where to end.
    Definition and initialization of character array
char a[5]
//If the number of characters is not enough, supplement 0; If the number of characters exceeds, an error will be reported
char str[7] = {'h','e','i','r','e','n'};
char str[] = {'h','e','i','r','e','n'};
cin>>str;//The length of the input string must be less than the length of the defined character array
cout<<str;//output

String handler

strcat(char s1[],const char s2[]);//Connect s2 to s1
strcpy(char s1[],const char s2[]);//Copy s2 to s1
strcmp(const char s1[],const char s2[]);//Compare S1, S2, S1 > S2, return 1, equal return 1, otherwise return - 1
strlen(char s[]);//Calculates the length of string s the actual length of string s, excluding \ 0

10.2 string in C + +

Definition and initialization of strings

//definition
string variable;
string str1;
//assignment
string str2 = "ShangHai";
string str3 = str2;
str3[3] = '2';//Assign a value to a character
//String array
string Array name[Constant expression]
string arr[3];

String handler

#include <iostream>
#include <algorithm>
#include <string>
string str;//Generate empty string
string s(str);//Generate a copy of the string str
string s(str, strbegin,strlen);//Take the part of the string str with the length of strlen starting from the subscript strbegin as the initial value of the string
string s(cstr, char_len);//With C_ Char before cstr of string type_ Len strings as the initial value of string s
string s(num ,c);//Generates a string of num c characters
string s(str, stridx);//Take the position from the beginning of the subscript stridx to the end of the string in the string str as the initial value of the string
size()and length();//Returns the number of characters of a string object
max_size();//Returns the maximum number of characters contained in a string object. If the number exceeds, length will be thrown_ Error exception
capacity();//The maximum number of characters a string object can contain before reallocating memory
>,>=,<,<=,==,!=//Support the comparison between string and C-string (such as STR < "hello"). When using >, > =, <, < = these operators, the characters are compared one by one in dictionary order according to the "current character characteristics", string ("aaaa") < string (AAAAA).    
compare();//It supports multi parameter processing and comparison with index value and length positioning substring. Returns an integer to represent the comparison result. The returned value has the following meanings: 0: equal 1: greater than - 1:
  
push_back() 
insert( size_type index, size_type count, CharT ch );//Insert count characters ch in the index position
insert( size_type index, const CharT* s );//Insert a constant string at the index position
insert( size_type index, const CharT* s, size_type n);//Insert constant string at index position
insert( size_type index, const basic_string& str );//Insert n characters in the constant string at the index position
insert( size_type index, const basic_string& str, size_type index_str, size_type n);//Insert the constant STR from the index position_ n characters from str
insert( size_type index, const basic_string& str,size_type index_str, size_type count = npos);//Insert the constant str from the index position_ str starts with count characters. The maximum value that count can represent is npos. This function does not constitute an overload. npos represents a constant and represents size_ The maximum value of T. If the find function of string does not find the specified character, it returns an npos
iterator insert( iterator pos, CharT ch );
iterator insert( const_iterator pos, CharT ch );
void insert( iterator pos, size_type n, CharT ch );//Insert n characters ch at the pos position pointed to by the iterator
iterator insert( const_iterator pos, size_type count, CharT ch );//Insert count characters ch at the pos position pointed to by the iterator
void insert( iterator pos, InputIt first, InputIt last );
iterator insert( const_iterator pos, InputIt first, InputIt last );
append() and + Operator
//Access string each string
string s1("yuanrui"); // Call constructor once
// Method 1: subscript method
for( int i = 0; i < s1.size() ; i++ )
     cout<<s1[i];
// Method 2: forward iterator
for( string::iterator iter = s1.begin();; iter < s1.end() ; iter++)
     cout<<*iter;
 // Method 3: reverse iterator
for(string::reverse_iterator riter = s1.rbegin(); ; riter < s1.rend() ; riter++)
     cout<<*riter;
 iterator erase(iterator p);//Delete the character indicated by p in the string
iterator erase(iterator first, iterator last);//Delete all characters on the iterator interval [first,last) in the string
string& erase(size_t pos = 0, size_t len = npos);//Delete the len characters from the index position pos in the string
void clear();//Delete all characters in the string
string& replace(size_t pos, size_t n, const char *s);//Replace the n characters of the current string starting from the pos index with the string s
string& replace(size_t pos, size_t n, size_t n1, char c); //Replace the n characters of the current string starting from the pos index with n1 characters c
string& replace(iterator i1, iterator i2, const char* s);//Replace the string in the current string [i1,i2) interval with the string s
//Tower () and toupper() functions or transform algorithm in STL
string s = "ABCDEFG";
for( int i = 0; i < s.size(); i++ )
     s[i] = tolower(s[i]);
transform(s.begin(),s.end(),s.begin(),::tolower);
size_t find (constchar* s, size_t pos = 0) const;//Starting from the pos index position of the current string, find the substring s and return the found position index, - 1 means that the substring cannot be found
size_t find (charc, size_t pos = 0) const;//Starting from the pos index position of the current string, find the character c and return the found position index, - 1 means that the character cannot be found
size_t rfind (constchar* s, size_t pos = npos) const;//Starting from the pos index position of the current string, reverse the search for the substring s and return the found position index, - 1 indicates that the substring cannot be found
size_t rfind (charc, size_t pos = npos) const;//Starting from the pos index position of the current string, reverse the search for the character c and return the found position index, - 1 indicates that the character cannot be found
size_tfind_first_of (const char* s, size_t pos = 0) const;//Starting from the pos index position of the current string, find the character of the substring s, and return the found position index, - 1 indicates that the character cannot be found
size_tfind_first_not_of (const char* s, size_t pos = 0) const;//Starting from the pos index position of the current string, find the first character not located in the substring s, and return the found position index, - 1 indicates that the character cannot be found
size_t find_last_of(const char* s, size_t pos = npos) const;//Starting from the pos index position of the current string, find the last character in the substring s, and return the found position index, - 1 indicates that no character can be found
size_tfind_last_not_of (const char* s, size_t pos = npos) const;//Starting from the pos index position of the current string, find the last character not located in the substring s, and return the found position index, - 1 indicates that the substring cannot be found
sort(s.begin(),s.end());
substr(pos,n);//The return string is n characters from the subscript pos
strtok()
char str[] = "I,am,a,student; hello world!";
const char *split = ",; !";
char *p2 = strtok(str,split);
while( p2 != NULL )
{
    cout<<p2<<endl;
    p2 = strtok(NULL,split);
}

11 pointers and references

11.1 pointer

A pointer is a variable whose value is the address of another variable. That is, the direct address of the memory location.
General form of declaration:

  • The data type is the data type of the variable pointed to by the pointer variable, * indicates that the subsequent variable is a pointer variable
data type *Pointer variable name;
int    *ip;    //Integer pointer 
double *dp;    //double pointer 
float  *fp;    //Floating point pointer 
char   *ch;    //Character pointer 

Initialization of pointer variables:

  • &Is the address operator, and the & variable name represents the address of the variable.
  • The data type of the variable must be consistent with the data type of the pointer variable.
  • For security reasons, pointers are sometimes initialized to NULL pointers (NULL or 0)
data type *Pointer variable name = &Variable name;
*Pointer variable name = &Variable name;
int a;
int *p = &a;
int *p2;
p2 = &a;

Reference to pointer variable:

  • &Take the address character * pointer operator (indirect operator), followed by the pointer variable, indicating the variable to which the pointer variable points.
  • &The priority of * is the same, and the combination method is from left to right. For ex amp le, & * P is equivalent to & (* P).
int x = 3;
int y;
int *p;
p = &x;
y = *p;//y = a

Pointer operation (address operation)

  • Arithmetic operation (moving pointer operation): addition and subtraction, self increase and self decrease.
  • The address obtained by p+n operation is p+n * sizeof (data type).
  • Two pointers of the same data type can perform addition and subtraction operations, which are generally used in array operations.
  • Relational operation: only when the pointer points to the same string of continuous storage units, such as an array. Compare with 0 to determine whether it is a null pointer.
  • Assignment operation: the variable address is assigned to the pointer variable, the array element address is assigned to the pointer variable, and the pointer variable is assigned to other pointer variables.
int arr[10],len;
int *p1 = &arr[2],*p2 = &arr[5];
 len = p2-p1;//Number of elements between arr[2] and arr[5] 3

new and delete operators

  • new - allocate memory space for variables;
  • You can judge whether the space allocation is successful by judging the value of the pointer returned by new.
  • delete free space
Pointer variable = new data type(initial value);
delete Pointer variable;
delete[] Pointer variable;//Release addresses assigned to multiple variables
int *ip;
ip= new int(1);
delete ip;
int *ip;
 ip= new int[10];
 for (int i = 0; i < 10;i++)
 {
	 ip[i] = i;
 }
 delete[] ip;
int a[3][4] = {0};

Pointers and arrays

  • The array name is the first address of the array, and eg:arr is the address of arr[0].
  • Accessing array elements: arr[i], (arr+i), (p+i), p[i]
  • Two dimensional array: arr + I = = & arr [i], arr [i] = = & arr [i] [0], * (arr[i]+j) == arr[i][j]
  • Pointer to access two-dimensional array: points to two-dimensional array elements and one-dimensional array
  • Array pointer: data type (* pointer variable name) [m]
int arr[10];
int *p1 = arr;// *p1 = &arr[0];
int a[3][5] = { 0 };
int(*ap)[5];
ap = a;
ap+1;//Represents the next one-dimensional array

Pointer and string

  • String array name: char ch[] = "heiren";char *p = ch;
  • String: char *p = "heiren";
  • Pointer assignment operation: char * p;p = "Heiren";
    Pointers and functions. Pointers can be used as parameters or return values of functions.

11.2 references

Reference can be regarded as an alias of data. This data can be found through this alias and the original name, which is similar to the shortcut in window.

  • The reference does not occupy memory space. It must be initialized at the same time as the definition, and no other data can be referenced.
  • When defining a reference, you need to add &, but you can't add &. Adding & when using means taking an address
    Reference variable declaration: data type & reference name = variable name;
int a;
int &b = a;//a and b represent the same variables with the same address.

A reference can be used as a function parameter or as a function return value.

void swap(int &r1, int &r2) {
    int temp = r1;
    r1 = r2;
    r2 = temp;
}
int &add1(int &r) {
	r += 1;
	return r;
}
int main()
{
	int a = 12;
	int b = add1(a);
	cout << a << "   "<<b << endl;//13  13
	return 0;
}

When a reference is used as a function return value, a reference to local data cannot be returned because the local data will be destroyed after the function call is completed.
When the function runs on the stack and runs out of functions, the subsequent function calls will overwrite the local data of the previous function.

int &add1(int &r) {
	r += 1;
	int res = r;
	return res;
}
void test()
{
	int xx = 123;
	int yy = 66;
}
int main()
{
	int a = 12;
	int &b = add1(a);
	int &c = add1(a);
	test();//Function call to overwrite the local data of the previous function
	cout << a << "   "<<b <<" "<< c<<endl;//14   -858993460 -858993460
	return 0;
}

12 custom data types

12.1 structure

Structures can contain structures of different data types.
Defines the general form of the structure

struct Structure type name
{
	Member type 1 member name 1;
	Member type 2 member name 2;
	... ...
	Member type n member name n;
};

Definition and initialization of structure variable name:

//Define the structure and declare the structure variable name
struct Structure type name
{
	Member type 1 member name 1;
	Member type 2 member name 2;
	... ...
	Member type n member name n;
}Variable name 1,Variable name 2,...Variable name n;
//Define the structure first
[struct] Structure type name variable name;
//Direct definition
struct 
{
	Member type 1 member name 1;
	Member type 2 member name 2;
	... ...
	Member type n member name n;
}Variable name 1,Variable name 2,...Variable name n;
struct  person
{
	int year;
	int age;
	string name;
}p1 = {2019,24,"heiren"}, p1 = { 2020,24,"heiren" };
struct  person
{
	int year;
	int age;
	string name;
};
struct person p1 = { 2019,24,"heiren" }, p1 = { 2020,24,"heiren" };
struct 
{
	int year;
	int age;
	string name;
}p1 = {2019,24,"heiren"}, p1 = { 2020,24,"heiren" };

Use of structure variables:

  • Structural variables of the same type can be assigned, but cannot be input or output
  • Member reference to structure variable: structure variable name. Member name
  • Reference format of pointer variable pointing to structure: pointer variable name - > member name;
    The definition, initialization and use of structure array are similar to structure variable and basic type array
struct person
{
	int year;
	int age;
	string name;
}p[2] ={ {2019,24,"heiren"}, { 2020,24,"heiren" }};//You can not specify the number of array elements
p[1].age;

There are three types of structure passing as a function: value passing, reference passing and pointer passing

12.2 structure size and byte alignment

In modern computers, the memory space is divided according to byte s. Theoretically, it seems that the access to any type of variable can start from any address, but the actual situation is that when accessing a specific type of variable, it is often accessed at a specific memory address, which requires various types of data to be arranged in space according to certain rules, Instead of sequential discharge one after another, this is alignment
     Why do I need byte alignment? Each hardware platform has a great difference in the processing of storage space. Some platforms can only access certain types of data from certain addresses. For example, some platforms start reading from the even address every time. If an int type (assumed to be a 32-bit system) is stored at the beginning of the even address, the 32bit data can be read out in one read cycle. If it is stored at the beginning of the odd address, it needs two read cycles, and the high and low bytes of the two read results can be pieced together to obtain the 32bit data.
Three concepts:

  • Self alignment value: the alignment value of the data type itself. The self alignment value of the structure or class is the largest value among its members. For example, the self alignment value of char type is 1 and the short type is 2;
  • Specified alignment value: the alignment value specified by the compiler or programmer. The specified alignment value of 32-bit MCU is 4 by default;
  • Valid alignment value: the smaller of the self alignment value and the specified alignment value.
    Three criteria for byte alignment
  • The first address of a structure variable can be divided by the size of its valid alignment value
  • The total size of the structure is an integer multiple of the valid alignment value of the structure.
  • The offset of each member of the structure from the first address of the structure is an integer multiple of the valid alignment value.
    You can use #pragma pack(n) to set variables in n-byte alignment
    for instance
//Specified alignment value = 8
struct st 
{
	// Empty structure size 1
	char c1;//1
	char c2;//2
	int i1;//8 the starting address of int should be an integer multiple of its length 4 according to the principle of byte alignment
	char c3;//12
	short s4;//According to the principle of byte alignment, the starting address of 12 short should be an integer multiple of its length 2. 12 + 2 = 12
	double d;//According to the principle of byte alignment, the starting address of 24 double should be an integer multiple of its length 8. 12 - > 16 + 8 = 24
	char c4;//32 24 + 4 = 28 the total size of the structure is an integral multiple of 8 28 - > 32
	int i2;//32  28+4 = 32
	int i3;//40   
	short s5;//40
};
cout << sizeof(st) << endl;//40
//Specified alignment value = 4
#pragma  pack(4)
struct st
{
	//1 empty structure size 1
	char c1;//1
	char c2;//2
	int i1;//8
	char c3;//12
	short s4;//12
	double d;//20
	char c4;//24
	int i2;//28
	int i3;//32
	short s5;//36
}s;
cout << sizeof(st) << endl;//36

12.3 Union

Several different variables share memory space starting at the same address.

  • The member type can be either a basic data type or a construction data type.
  • When initializing a common body variable, only the first member can be assigned a value.
  • The length of memory occupied by common body variables is equal to the longest member length.
  • Only one member of a common body variable can function at a time. During assignment, members will overwrite each other, and the last assigned member will function.
    definition
union Community type name
{
    Member type 1 member name 1;
	Member type 2 member name 2;
	... ...
	Member type n member name n;
};

initialization

union data
{
	int i;
	float f;
	char c;
}x = {123};
union data
{
	float f;
	int i;
	char c;
};
data x = {12.3};
union 
{
	char c;
	int i;
	float f;
}x = {'y'};

quote

Community variable name.member name;
union data
{
	int i;
	float f;
	char c;
}x = {12};
int main()
{
	cout << x.i << " " << x.f << " " << x.c << endl;//12 1.68156e-44 
	x.c = 'c';
	cout << x.i <<" "<< x.f << " " << x.c << endl;//99 1.38729e-43 c
	return 0;
}

12.4 enum and typedef declarations

Enumeration has been introduced in the previous chapter, so I won't repeat it here.
typedef - defines a new type name for an existing data type. Variables cannot be defined.
Typedef declaration format: typedef type name type identifier;

typedef char *CP;
typedef int INTEGER;

13 object oriented

Type 13.1

  • Class is also a data type.

Class declaration:

class Class name
{
	public:
		Public data members ;
		public functions ;
	private:
		Private data member;
		Private member function;
	protected:
		Protect data members;
		Protect member functions;
};

Definition of member function: in class, out of class, out of class inline function

//Out of class
 Return type class name:Member function name(parameter list)
{
	Function body;
}
//Inline functions: out of class
inline Return type class name:Member function name(parameter list)
{
	Function body;
}

The code of the inline function will be directly embedded into the calling function, which can save the call time. If the member function is defined in the class, it will be automatically an inline function.

13.2 access rights of class members and class encapsulation

  • Unlike Java and C # different, public, private and protected in C + + can only modify class members, not classes. Classes in C + + do not share private ownership
  • There is no restriction on access rights inside the class. You can access each other.
  • In the class defined by class in C + +, the default access permission of its members is private.
Out of classDerived classWithin class
publicYYY
protectedNYY
privateNNY

13.3 object

//1. Declare classes and define objects at the same time
class Class name
{
	Class body;
}Object name list;
//2. First declare the class and then define the object
 Class name object name(parameter list);//() may not be written when the parameter list is empty
//3. Define the object directly without class name
class 
{
	Class body;
}Object name list;
//4. Create objects on the heap
Person p(123, "yar");//Create object on stack
Person *pp = new Person(234,"yar");//Create objects on the heap

Note: you cannot initialize its data members while defining a class, because the class is not an entity, which is illegal, but can be compiled and run
Reference of object member: object name. Data member name or object name. Member function name (parameter list)

13.4 constructor

Is a special member function. Its main function is to allocate storage space for objects and assign initial values to class member variables

  • The constructor name must be the same as the class name
  • There are no return values and return types
  • The created object is called automatically, which does not need to be called by the user, and is only used once
  • Class does not define any constructor. The compilation system will automatically generate a default parameterless constructor for this class
    Constructor definition
//1. Definition in class 2. Declaration in class, definition outside class
[Class name::]Constructor name(parameter list)
{
	Function body
}

create object

Class name object name(parameter list);//() may not be written when the parameter list is empty

Constructor with default parameters

class Person
{
public:
	Person(int = 0,string = "Zhang San");
	void show();
private:
	int age;
	string name;
};
Person::Person(int a, string s)
{
	cout<<a<<" "<<s<<endl;
	age = a;
	name = s;
}
void Person::show()
{
	cout << "age="<<age << endl;
	cout << "name=" <<name << endl;
}
int main()
{
     Person p; //0 sheets 3
	Person p2(12);//12 sheets three
	Person p3(123, "yar");//123 yar
	return 0;
}

Constructor with parameter initialization table

Class name::Constructor name(parameter list):Parameter initialization table
{
	Function body;
}
General form of parameter initialization list:
Parameter name 1(Initial value 1),Parameter name 2(Initial value 2),...,Parameter name n(initial value n)
class Person
{
public:
	Person(int = 0,string = "Zhang San");
	void show();
private:
	int age;
	string name;
};
Person::Person(int a, string s):age(a),name(s)
{
	cout << a << " " << s << endl;
}

Constructor overloading: the constructor name is the same, and the number and type of parameters are different.

class Person
{
public:
	Person();
	Person(int = 0,string = "Zhang San");
	Person(double,string);
	void show();
private:
	int age;
	double height;
	string name;
};
...

copy constructor

Class name::Class name(Class name&Object name)
{
	Function body;
}
class Person
{
public:
	Person(Person &p);//Declare copy constructor
	Person(int = 0,string = "Zhang San");
	void show();
private:
	int age;
	string name;
};
Person::Person(Person &p)//Define copy constructor
{
	cout << "copy constructor " << endl;
	age = 0;
	name = "ABC";
}
Person::Person(int a, string s):age(a),name(s)
{
	cout << a << " " << s << endl;
}
int main()
{
	Person p(123, "yar");
	Person p2(p);
	p2.show();
	return 0;
}
//output
123 yar
 copy constructor 
age=0
name=ABC

13.5 destructor

Is a special member function. When the life cycle of an object ends, it is used to release the memory space allocated to the object, love you, and do some cleaning work.

  • Destructor name and class name must be the same.
  • Destructor name must be preceded by a tilde ~.
  • No parameters, no return value, cannot be overloaded.
  • There can only be one destructor in a class.
  • If there is no destructor defined, the compilation system will automatically generate a default destructor for and this class.
    Definition of destructor:
//1. Definition in class 2. Declaration in class, definition outside class
[Class name::]~Destructor name()
{
	Function body;
}

13.6 object pointer

Declaration and use of object pointers

Class name *Object pointer name;
Object pointer = &Object name;
//Access object members
 Object pointer->Data member name
 Object pointer->Member function name(parameter list)
Person p(123, "yar");
Person* pp = &p;
Person* pp2 = new Person(234,"yar")
pp->show();

Pointer to object member

Data member type *Pointer variable name = &Object name.Data member name;
Function type (Class name::*Pointer variable name)(parameter list);
Pointer variable name=&Class name::Member function name;
(Object name.*Pointer variable name)(parameter list);
Person p(123, "yar");
void(Person::*pfun)();
pfun = &Person::show;
(p.*pfun)();

this pointer
Each member function has a special pointer this, which always points to the object operated by the currently called member function

class Person
{
public:
	Person(int = 0,string = "Zhang San");
	void show();
private:
	int age;
	string name;
};
Person::Person(int a, string s):age(a),name(s)
{
	cout << a << " " << s << endl;
}
void Person::show()
{
	cout << "age="<<this->age << endl;
	cout << "name=" <<this->name << endl;
}

13.7 static members

Members starting with the keyword static are static members, which are shared by multiple classes.

  • static member variable belongs to a class, not a specific object
  • Static member functions can only access static data members in a class
    Static data member
//In class declaration, out of class definition
class xxx
{
	static Data type static data member name;
}
Data type class name::Static data member name=initial value
//visit
 Class name::Static data member name;
Object name.Static data member name;
Object pointer name->Static data member name;

Static member function

//In class declaration, out of class definition
class xxx
{
	static Return value type static member function name(parameter list);
}
Return value type class name::Static member function name(parameter list)
{
	Function body;
}
//visit
 Class name::Static member function name(parameter list);
Object name.Static member function name(parameter list);
Object pointer name->Static member function name(parameter list);

13.8 friends

With the help of friends, member functions in other classes and functions in the global scope can access the private members of the current class.
friend function

  • The friend function is not a member function of a class, so there is no this pointer, and the object must be passed through parameters.
  • The name of an object member cannot be directly referenced in a friend function. The member of the object can only be referenced through the object or object pointer passed in by the formal parameter.
//1. Declare a non member function as a friend function
class Person
{
public:
	Person(int = 0,string = "Zhang San");
	friend void show(Person *pper);//Declare show as a friend function
private:
	int age;
	string name;
};
Person::Person(int a, string s):age(a),name(s)
{
	cout << a << " " << s << endl;
}
void show(Person *pper)
{
	cout << "age="<< pper->age << endl;
	cout << "name=" << pper->name << endl;
}
int main()
{;
	Person *pp = new Person(234,"yar");
	show(pp);
	system("pause");
	return 0;
}
//2. Declare member functions of other classes as friend functions
//Member functions in person can access private member variables in MobilePhone
class MobilePhone;//Advance declaration
//Declare the Person class
class Person
{
public:
	Person(int = 0,string = "Zhang San");
	void show(MobilePhone *mp);
private:
	int age;
	string name;
};
//Declare the MobilePhone class
class MobilePhone
{
public:
	MobilePhone();
	friend void Person::show(MobilePhone *mp);
private:
	int year;
	int memory;
	string name;
};
MobilePhone::MobilePhone()
{
	year = 1;
	memory = 4;
	name = "iphone 6s";
}
Person::Person(int a, string s):age(a),name(s)
{
	cout << a << " " << s << endl;
}
void Person::show(MobilePhone *mp)
{
	cout << mp->year << "year  " << mp->memory << "G " << mp->name << endl;
}
int main()
{
	Person *pp = new Person(234,"yar");
	MobilePhone *mp = new MobilePhone;
	pp->show(mp);
	system("pause");
	return 0;
}

Friend class
When a class is a friend of another class, it is called a friend class. All member functions of a friend class are friend members of another class.
Syntax form: friend [class] friend class name

  • Friend relationships between classes cannot be passed
  • The friend relationship between classes is one-way
  • Friend relationships cannot be inherited
class HardDisk
{
public:
	HardDisk();
	friend class Computer;
private:
	int capacity;
	int speed;
	string brand;
};
HardDisk::HardDisk():capacity(128),speed(0),brand("Samsung"){
}
class Computer
{
public:
	Computer(HardDisk hd);
	void start();
private:
	string userName;
	string name;
	int ram;
	string cpu;
	int osType;
	HardDisk hardDisk;
	
};
Computer::Computer(HardDisk hd):userName("yar"),name("YAR-PC"),ram(16),cpu("i7-4710"),osType(64)
{
	cout << "Creating computer..." << endl;
	this->hardDisk = hd;
	this->hardDisk.speed = 5400;
	cout << "Hard disk rotation...speed = " << this->hardDisk.speed << "turn/minute" << endl;
	
}
void Computer::start()
{
	
	cout << hardDisk.brand << " " << hardDisk.capacity << "G" << hardDisk.speed << "turn/minute" << endl;
	cout << "The notebook starts running..." << endl;
}
int main()
{
	HardDisk hd;
	Computer cp(hd);
	cp.start();
	system("pause");
	return 0;
}

13.9 difference between class and struct

  • The structure of C language is introduced to ensure the compatibility with C program.
  • The structure in c language does not allow the definition of function members and has no access control rights.
  • c + + introduces object-oriented features such as member function, access control permission, inheritance, polymorphism and so on.
  • In C language, the size of empty structure is 0, while the size of C + + empty structure is 1.
  • Members in class are private by default, and members in struct are public by default.
  • class inheritance defaults to private inheritance, while struct inheritance defaults to public inheritance.
  • class can use templates, but struct cannot.
    for instance:
//The default permission of the structure is public
struct person
{
	void show();
	string name;
	int age;
};
int main()
{
	person p;
	p.name = "heiren";
	p.age = 666;
	p.show();
	cout <<"name="<< p.name <<" age="<< p.age << endl;
	system("pause");
	return 0;
}

Change struct to class and run with an error.

14 inheritance and derivation

14.1 overview of inheritance and derivation

Inheritance is to create a new class based on an existing class. The existing class is called the base class or parent class, and the newly established class is called the derived class and child class; Derivation and inheritance are a concept from different angles. Inheritance is that the son inherits the father's industry, and derivation is that the father inherits the industry to his son.

  • A base class can derive multiple derived classes, and a derived class can inherit multiple base classes
    Declaration of derived classes:
//The inheritance method is optional. The default is private. There are also public and protected
class Derived class name:[Inheritance mode]Base class name
{
	Newly added member declaration of derived class;
};

Inheritance method:

  • The access properties of the public and protected members of the public base class remain unchanged, and the private members are not visible.
  • Private - public members and protected members of the base class become private members, which can only be accessed directly by member functions of derived classes, and private members are not visible.
  • Protected - the public and protected members of the base class become protected members, which can only be accessed directly by the member functions of the derived class, and the private members are not visible.
Inheritance method / base class memberpublic memberprotected memberprivate member
publicpublicprotectedinvisible
protectedprotectedprotectedinvisible
privateprivateprivateinvisible
  • Using the using keyword, you can change the access rights of base class members in derived classes; Using can only modify the access permissions of public and protected members in the base class.
class Base
{
public:
	void show();
protected:
	int aa;
	double dd;
};
void Base::show(){
}
class Person:public Base
{
public:
	using Base::aa;//Change the protected member of the base class to public
	using Base::dd;//Change the protected member of the base class to public
private:
	using Base::show;//Change the public member of the base class to private
	string name;
};
int main()
{
	Person *p = new Person();
	p->aa = 12;
	p->dd = 12.3;
	p->show();//error
	delete p;
	return 0;
}

Constructors and destructors of derived classes

  • Execute the constructor of the base class first, and then the constructor of the derived class
  • First execute the destructor of the derived class, and then execute the destructor of the base class.
  • Constructor of derived class: derived class name (total parameter list): base class name (base class parameter list), sub object name 1 (parameter list) {constructor body;}
class Base
{
public:
	Base(int, double);
	~Base();
private:
	int aa;
	double dd;
};
Base::Base(int a, double d) :aa(a), dd(d)
{
	cout << "Base Class Constructor!!!" << endl;
}
Base::~Base()
{
	cout << "Base Class Destructor!!!" << endl;
}
class Person:public Base
{
public:
	Person(int,double,string);
	~Person();
private:
	string name;
};
Person::Person(int a,double d,string str):Base(a,d),name(str)
{
	cout << "Person Class Constructor!!!" << endl;
}
Person::~Person()
{
	cout << "Person Class Destructor!!!" << endl;
}
int main()
{
	cout << "establish Person object..." << endl;
	Person *p = new Person(1,2,"yar");
	cout << "delete Person object...." << endl;
	delete p;
	system("pause");
	return 0;
}

14.2 multiple inheritance

A derived class inherits the behavior of multiple base classes at the same time.

Multi inheritance is easy to make the code logic complex and confused, which has been controversial. It is rarely used in small and medium-sized projects. Later, Java, C#, PHP and so on simply cancelled multi inheritance.

General form of multiple inheritance derived class declaration:

class Derived class name:Inheritance method 1 base class 1,Inheritance method 2 base class 2
{
	Derived class principal;
};

Constructor for multiple inheritance derived classes:

Derived class name(Total parameter list): Base class name 1(Base class parameter list 1),Base class name 2(Base class parameter list 2),
Sub object name 1,...(parameter list)
{
	Constructor body;
}`

Ambiguity problem: multiple base classes have members with the same name, so the access is not unique.

  • 1. Class name: member name with the same name;
  • 2. A derived class defines a member with the same name and accesses the member with the same name of the derived class.

14.3 virtual base class

c + + introduces a virtual base class so that when a derived class inherits an indirect common base class, only one member with the same name is retained.

  • The purpose of virtual inheritance is to make a class declare that it is willing to share its base class. The shared base class is called Virtual Base Class.
  • A member of a derived class with the same name takes precedence over a virtual base class
    Declaration of virtual base class: class derived class name: base class name of virtual inheritance mode
class  A//virtual base class
{
protected:
	int a;
};
class B: virtual public A
{
protected:
	int b;
};
class C:virtual public A
{
protected:
	int c;
};
class D:public B,public C
{
protected:
	int d;
	void show()
	{
		b = 123;
		c = 23;
		a = 1;
	}
};
  • If one of the classes in B or C defines a, there will be no ambiguity. A of the derived class has higher priority than a of the virtual base class.
  • If a is defined in both B and C, D's direct access to a will cause ambiguity.
    Application: iostream, istream, ostream, base in c + +_ io

Polymorphic and virtual functions

15.1 upward transformation

For data type conversion, the compiler will directly throw away the decimal part (not round)

int a = 66.9;
printf("%d\n", a);//66
float b = 66;
printf("%f\n", b);//66.000000
  • A derived class can only be assigned to a base class (called an upward transformation in C + +): a derived class object can be assigned to a base class object, a derived class pointer can be assigned to a base class pointer, and a derived class reference can be assigned to a base class reference
  • The derived class object is assigned to the base class object, and the new members of the derived class are discarded; The derived class pointer is assigned to the base class pointer. It does not copy the members of the object or modify the data of the object itself, but only changes the pointer; The derived class reference is assigned to the base class reference, which is the same as that of the pointer

After the transformation, only the members inherited from the base class (including member variables and member functions) can be accessed through the objects, pointers and references of the base class, but the new members of the derived class cannot be accessed

15.2 polymorphism

Different objects can use the same function name to call functions with different contents.

  • Static polymorphism - when the program is compiled, the system determines which function to call, such as function overloading and static polymorphism
  • Dynamic polymorphism - dynamically determine which function to call during program operation, which is realized by virtual functions.

15.3 virtual function

An important means to realize program polymorphism is to use the pointer of the base class object to access the function with the same name of the derived class object.

  • The function in the base class is declared as a virtual function, and the function with the same name in the derived class is automatically declared as a virtual function.
  • Declaration form: virtual function type function name (parameter list);
  • Constructors cannot be declared as virtual functions, destructors can be declared as virtual functions.
class  A
{
public:
	virtual void show()
	{
		cout << "A show" << endl;
	}
};
class B:  public A
{
public:
	void show()
	{
		cout << "B show" << endl;
	}
};
int main()
{
	
	B b;
	b.show();//B show
	A *pA = &b;
	pA->show();//B show if the show method is not declared as a virtual function with virtual, A show will be output here
	
	system("pause");
	return 0;
}

15.4 pure virtual function

No specific operations are performed in the base class, and only a unified virtual function is provided for the derived class, which is declared as a virtual function.

class  A
{
public:
	virtual void show() = 0;
};
class B:  public A
{
public:
	void show()
	{
		cout << "B show" << endl;
	}
};

Abstract class: a class containing pure virtual functions is called an abstract class. Because pure virtual functions cannot be called, they cannot use abstract classes to create objects, also known as abstract base classes.

16 operator overloading

The so-called overloading is to give new meaning. Function Overloading allows a function name to have multiple functions and perform different operations in different situations. Operator Overloading is also a truth. The same operator can have different functions.

  • Operator overloading is realized by function, which is essentially function overloading.

Allow overloaded operators

Operator nameoperator
Binocular arithmetic operator+,-,*,,,%
Relational operator==,!=,<,>,<=,>=
Logical operator
unary operator +, -, * (pointer), & (take address)
Self increasing and self decreasing operator++,–
Bitwise Operators |,&,-,......,<<,>>
Assignment Operators =,+=,-=,*=,/=,%=,&=,!=,^=,<<= ,>>=
Space allocation and releasenew,delete,new[],delete[]
Other Operators () (function call), - > (member access), - > * (member pointer access), (comma)
  • Overloaded operators are not allowed
Operator nameoperator
member access operator .
Member pointer access operator. *
Domain operator::
length operator sizeof()
Conditional operator?:

16.1 definitions

Rules for overloaded operators:

  • You cannot define new operators by yourself. You can only overload existing C + + operators.
  • The number of operator operands cannot be changed.
  • The priority and associativity of operators cannot be changed
  • It shall be similar to the standard type operation function to avoid affecting readability.
    General format:
Function type operator operator(parameter list)
{
	Function body
}
//Take chestnuts for example: define a vector class. Through operator overloading, you can operate with +.
class Vector3
{
public:
	Vector3();
	Vector3(double x,double y,double z);
public:
	Vector3 operator+(const Vector3 &A)const;
	void display()const;
private:
	double m_x;
	double m_y;
	double m_z;
};
Vector3::Vector3() :m_x(0.0), m_y(0.0), m_z(0.0) {}
Vector3::Vector3(double x, double y,double z) : m_x(x), m_y(y), m_z(z) {}
//Operator overloading 
Vector3 Vector3::operator+(const Vector3 &A) const
{
	Vector3 B;
	B.m_x = this->m_x + A.m_x;
	B.m_y = this->m_y + A.m_y;
	B.m_z = this->m_z + A.m_z;
	return B;
}
void  Vector3::display()const
{
	cout<<"(" << m_x << "," << m_y << "," << m_z << ")" << endl;
}

16.2 form

There are two forms of operator overloading: overloaded function as a member of a class and overloaded function as a friend function of a class
According to different operator operands: binocular operator as class member function, monocular operator as class member function, binocular operator as class friend function, and monocular operator as class friend function.

  • When the binocular operator is used as a friend function, two parameters need to be specified.
  • Operator overloaded functions can be called explicitly as class member functions.
class Vector3
{
public:
	Vector3();
	Vector3(double x,double y,double z);
public:
	Vector3 operator+(const Vector3 &A)const;
	Vector3 operator++();
	friend Vector3 operator-(const Vector3 &v1, const Vector3 &v2);
	friend Vector3 operator--(Vector3 &v);
	void display()const;
private:
	double m_x;
	double m_y;
	double m_z;
};
Vector3::Vector3() :m_x(0.0), m_y(0.0), m_z(0.0) {}
Vector3::Vector3(double x, double y,double z) : m_x(x), m_y(y), m_z(z) {}
//Operator overloading 
Vector3 Vector3::operator+(const Vector3 &A) const
{
	Vector3 B;
	B.m_x = this->m_x + A.m_x;
	B.m_y = this->m_y + A.m_y;
	B.m_z = this->m_z + A.m_z;
	return B;
}
Vector3 Vector3::operator++()
{
	this->m_x ++;
	this->m_y ++;
	this->m_z ++;
	return *this;
}
void  Vector3::display()const
{
	cout<<"(" << m_x << "," << m_y << "," << m_z << ")" << endl;
}
Vector3 operator-(const Vector3 &v1,const Vector3 &v2)
{
	Vector3 B(v1.m_x - v2.m_x, v1.m_y - v2.m_y, v1.m_z - v2.m_z);
	return B;
}
Vector3 operator--( Vector3 &v)
{
	v.m_x--;
	v.m_y--;
	v.m_z --;
	return v;
}
int main()
{
	Vector3 v1(1, 2, 3);
	Vector3 v2(2, 3, 2);
	
	++v1;//v1.operator++();  Functions that are members of a class can be called explicitly
	v1.display();
	--v2;
	v2.display();
	Vector3 v3 = v1 + v2;// v1.operator+(v2); Functions that are members of a class can be called explicitly
	v3.display();
	Vector3 v4 = v1 - v2;
	v4.display();
	return 0;
}

16.3 overloading of common operators

1. Self increase and self decrease:

//Prepositive operator + + a --a
operator++()
operator--()
operator++(Vector3 &v)
operator--(Vector3 &v)
//Post operator a-- a++
operator++(int)
operator--(int)
operator++(Vector3 &v,int)
operator--(Vector3 &v,int)

2. Assignment operator:

String& String::operator=(String &s)
{
  if(this!=&s)
  {
  		delete[] str;
  		int length = strlen(s.str);
  		str = new char[length+1];
  		strcpy(str,s.str);
  }
  return (*this)
}

3. Input / output operator overloading

 friend ostream &operator<<( ostream &output, 
                                       const Vector3 &v )
      { 
         output << "F : " <<v.m_x<< " I : " << v.m_y<<v.m_z;
         return output;            
      }
 
      friend istream &operator>>( istream  &input, Vector3 &v )
      { 
         input >> v.m_x>> v.m_y>>v.m_z;
         return input;            
      }

16.4 implementation of type conversion

  • The function type and parameters are not specified. The type of the return value is determined by the type name.
  • Type conversion functions can only be member functions, not friend functions.
    General form of type conversion function:
operator Type name()
{
	Conversion statement;
}
class Vector3
{
public:
	Vector3();
	Vector3(double x,double y,double z);
public:
	Vector3 operator+(const Vector3 &A)const;
	Vector3 operator++();
	friend Vector3 operator-(const Vector3 &v1, const Vector3 &v2);
	friend Vector3 operator--(Vector3 &v,int);
	operator double()
	{
		return m_x + m_y + m_z;
	}
	void display()const;
private:
	double m_x;
	double m_y;
	double m_z;
};
int main()
{
	Vector3 v1(1, 2, 3);
	double d = v1;
	cout << d << endl;//6
	return 0;
}

17 IO stream

Stream - a continuous collection of data.

17.1 stream classes and objects

  • Input stream - a stream from an input device to memory.
  • Output stream - the stream that flows out of the device from memory.
  • Memory buffer - used to store data in the stream.

Input / output process: keyboard input = "keyboard buffer = (carriage return trigger)" program input buffer = "> >" extract data
                        Output buffer = (buffer full or endl) "< <" sent to display
Input / output stream class:
iostream: ios ,istream,ostream,iostream
fstream: ifstream,ofstream,fstream
strstream: istrstream,ostrstream,strstream

  • istream is a stream class for input, and cin is the object of this class.
  • ostream is a stream class for output, and cout is the object of this class.
  • ifstream is a class used to read data from a file.
  • ofstream is a class used to write data to a file.
  • iostream is a class that can be used for both input and output.
  • fstream is a class that can read data from and write data to files.
  • istrstream input string class
  • ostrstream output string class
  • strstream input / output string stream class

17.2 standard I / O flow

The input / output stream Library (iostream) of C + + defines four standard stream objects: CIN (standard input stream - Keyboard), cout (standard output stream - screen), cerr (standard error stream - screen), and clog (standard error stream - screen)

  • cerr outputs information directly to the display without using buffer; The information output to the clog will be stored in the buffer first, and will not be output to the screen until the buffer is full or refreshed.
  • cout is the object of ostream class. The parameterless constructor and copy constructor of ostream class are private, so the object of ostream class cannot be defined.
  • When using > > to extract data, the system will skip white space characters such as spaces, tabs, line breaks, etc. So when you enter values for a set of variables, you can separate them.
  • If you enter a string, it also skips white space characters, and the string end flag \ 0 will be added at the end of the string.
int  x;
double y;
cin>>x>>y;
//Enter 22 66.0. Data can be separated by spaces, tabs, and carriage returns
char str[10];
cin>>str;//hei ren string contains only hei Hei \ 0

Member functions in the input stream

  • get functions: cin.get(), cin.get(ch) (non-zero value is returned successfully, otherwise 0 is returned), CIN. get (character array (or character pointer), number of characters n, termination character)
char c = cin.get();//Get a character
while ((c = cin.get()) != EOF)//Loop reads until line breaks
{
	cout << c;
}


char ch;
cin.get(ch);
while (cin.get(ch))//Read successful cycle
{
	cout << ch;
}

char arr[5];
cin.get(arr, 5, '\n');//Enter the hearen result \ 0
  • Getline function: cin.getline (character array (or character pointer), number of characters n, termination flag character)
    Read the character, know the termination character, or read n-1 characters, and assign it to the specified character array (or character pointer)
char arr0[30],arr1[30],arr2[40];
cin>>arr0;//End 'Heiren' when a space, tab, or carriage return is encountered
cin.getline(arr1,30);//The maximum number of characters is 29, and the carriage return end "Hello World" is encountered
cin.getline(arr2,40,'*');//Up to 39, encounter * end "yar"
//Enter Heiren Hello World
//yar*123
  • cin.peek() does not skip spaces and carriage returns in the input stream. When the input stream has ended, cin.peek() returns EOF.
  • ignore(int n =1, int delim = EOF)
int n;
 cin.ignore(5, 'Y');//Skip the first 5 characters or characters before Y, 'Y' takes precedence
 cin >> n;
 //Enter 1234567 - > 67 1234567y345 - > 345

//Input 2020.2.23
int year,month,day;
cin >> year ;
cin.ignore() >> month ; //Skip '.' with ignore
 cin.ignore() >> day;
cin.ignore();   //Skip end of line '\ n'

 cout<< setfill('0') << setw(2) << month ;//Set padding character '\ 0', output width 2
 cout << "-" << setw(2) << day << "-" << setw(4) << year << endl;
  • putback(char c), you can insert a character at the beginning of the input stream.

Output stream object

  • Insert endl - output all data, insert line breaks, and empty the buffer
  • \n - output line wrap, do not empty buffer
  • Cout.put (parameter) outputs a single character (it can be a character or ASII code)

Format output
Flow operators defined in iomanip:

  • *It is not a part of the operator. The asterisk indicates that the operator is used without any operator. For example, by default, the integer is output in decimal form, which is equivalent to the dec operator
Flow manipulation operatoreffect
*decOutput integers in decimal form
hexOutputs an integer in hexadecimal form
octOutput integer in octal form
fixedOutput floating point numbers as ordinary decimals
scientificOutput floating-point numbers as scientific counting
leftLeft justified, that is, fill characters are added to the right when the width is insufficient
*rightRight justified, that is, fill characters are added to the left when the width is insufficient
setbase(b)Sets the base number when outputting integers, b=8, 10, or 16
setw(w)Specify that the output width is w characters, or read in W characters when entering a string
setfill©When the output width is specified, it is filled with the character c when the output width is insufficient (filled with spaces by default)
setprecision(n)Sets the precision of the output floating-point number to n. In the case of non fixed and non scientific output, n is the largest number of significant digits. If the number of significant digits exceeds n, the decimal part will be rounded off, or it will be automatically output by scientific counting method and a total of N significant digits will be reserved. When using fixed and scientific output, n is the number of digits that should be reserved after the decimal point.
setiosflags(flag)Set an output format flag to 1
resetiosflags(flag)Set an output format flag to 0
boolaphaIt is not common to output true and false as strings
*noboolalphaOutput true and false as 0 and 1
showbaseOutputs the hexadecimal prefix representing the value
*noshowbaseDo not output the prefix of hexadecimal. Representing the value
showpointAlways output decimal point
*noshowpointThe decimal point is displayed only when the decimal part exists
showposDisplay in non negative values+
*noshowposDo not display in non negative values+
*skipwsSkip white space characters when entering
noskipwsDo not skip white space characters when entering
uppercaseA to e are used in hexadecimal numbers. If the prefix is output, the prefix will output 0X, and the scientific counting method will output E
*nouppercaseUse a~e in hexadecimal numbers. If the prefix is output, the prefix will output 0x and the scientific counting method will output E.
internalThe symbol (sign) of the value is aligned to the left within the specified width, the value is aligned to the right, and the middle is filled with filling characters.
  • Usage of stream operator: cout < < hex < < 12 < < "," < 24// c,18

setiosflags() operator
The setiosflags() operator is actually a library function. It takes some flags as parameters. These flags can be the following values defined in the iostream header file. Their meaning is the same as that of the operator with the same name.

Signeffect
ios::leftThe output data is aligned to the left within a wide range of this field
ios::rightThe output data is aligned to the right within a wide range of this field
ios::internalThe sign bit of the value is aligned to the left within the field width, the value is aligned to the right, and the middle is filled with filling characters
ios::decSet the cardinality of an integer to 10
ios::octSet the cardinality of an integer to 8
ios::hexSet the cardinality of an integer to 16
ios::showbaseForce the cardinality of the output integer (octal number starts with 0 and hexadecimal number starts with 0x)
ios::showpointForces the output of the dot and mantissa of a floating-point number 0
ios::uppercaseIt is expressed in uppercase when outputting letters in scientific notation format E and hexadecimal
ios::showposThe "+" sign is displayed for positive numbers
ios::scientificFloating point number scientific notation format output
ios::fixedFloating point number fixed-point format (decimal form) output
ios::unitbufRefresh all streams after each output
ios::stdioClear stdout, stderr after each output
  • Multiple flags can be connected by the | operator, indicating that they are set at the same time. For example:
cout << setiosflags(ios::scientific|ios::showpos) << 12.34;//+1.234000e+001
  • If two conflicting flags are set at the same time, the result may be that neither flag works. The original flag should be cleared with resetiosflags
cout << setiosflags(ios::fixed) << 12.34 << endl;
cout << resetiosflags(ios::fixed) << setiosflags(ios::scientific | ios::showpos) << 12.34 << endl;

Member functions in ostream class:

Member functionFlow manipulation operators with the same effectexplain
precision(n)setprecision(n)Sets the precision of the output floating-point number to n.
width(w)setw(w)Specifies that the output width is w characters.
fill©setfill ©When the output width is specified, it is filled with the character c when the output width is insufficient (filled with spaces by default).
setf(flag)setiosflags(flag)Set an output format flag to 1.
unsetf(flag)resetiosflags(flag)Set an output format flag to 0.
  • The flags used in setf and unsetf functions are exactly the same as those used in setiosflags and resetiosflags.
cout.setf(ios::scientific);
cout.precision(8);
cout << 12.23 << endl;//1.22300000e+001

18 file operation

File - refers to the data set stored on external media. According to the data organization, files are divided into two types: ASCII file (text / character) and binary file (internal format / byte)

  • ASCII file output is still a binary file. The data form is the same. For numerical data, the output is different

18.1 document classes and objects

There are three classes in the C + + standard class library that can be used for file operations. They are collectively referred to as file stream classes. The three classes are:

  • ifstream: an input stream class used to read data from a file.
  • ofstream: output stream class, which is used to write human data to a file.
  • Fsstream: input / output stream class, which can be used to read data from and write human data to files.
    File stream object definition:
#include <fstream>
ifstream in;
ofstream out;
fstream inout;

18.2 opening files

  • Purpose of opening a file: to establish an association between an object and a file and indicate how the file is used
  • There are two ways to open a file: the open function and the constructor

Open function: void open(const char* szFileName, int mode);

Pattern markApplicable objecteffect
ios::inifstream fstreamOpen the file for reading data. If the file does not exist, there is an error opening it.
ios::outofstream fstreamOpen file for writing data. If the file does not exist, create a new file; If the file already exists, the original contents will be cleared when it is opened.
ios::appofstream fstreamOpen a file to add data to its tail. If the file does not exist, create a new one.
ios::ateifstreamOpen an existing file and point the file read pointer to the end of the file (the concept of read-write refers will be explained later). If the file does not exist, there is an error opening it.
ios:: truncofstreamIt is the same as ios:: out when used alone.
ios::binaryifstream ofstream fstreamOpen the file in binary mode. If this mode is not specified, it is opened in text mode.
ios::in | ios::outfstreamOpen an existing file to read its contents or write data to it. When the file is first opened, the original content remains unchanged. If the file does not exist, there is an error opening it.
ios::in | ios::outofstreamOpen an existing file and write data to it. When the file is first opened, the original content remains unchanged. If the file does not exist, there is an error opening it.
ios::inios::out | ios::truncfstream

ios::binary can be used in combination with other schema tags, for example:

  • ios::in | ios::binary means to open the file in binary mode by reading.
  • ios::out | ios::binary means to open the file in binary mode by writing.

Constructor of stream class
eg:ifstream::ifstream (const char* szFileName, int mode = ios::in, int);

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    ifstream inFile("c:\\tmp\\test.txt", ios::in);
    if (inFile)
        inFile.close();
    else
        cout << "test.txt doesn't exist" << endl;
    ofstream oFile("test1.txt", ios::out);
    if (!oFile)
        cout << "error 1";
    else
        oFile.close();
    fstream oFile2("tmp\\test2.txt", ios::out | ios::in);
    if (!oFile2)
        cout << "error 2";
    else
        oFile.close();
    return 0;
}

18.3 reading and writing of text files

For text files, you can use cin and cout to read and write.
eg: write a program to output the integers in the file i.txt in reverse order to o.txt. (12 34 56 78 90 -> 90 78 56 34 12)

#include <iostream>
#include <fstream>
using namespace std;
int arr[100];
int main()
{

	int num = 0;
	ifstream inFile("i.txt", ios::in);//Text mode on
	if (!inFile)
		return 0;//Open failed
	ofstream outFile("o.txt",ios::out);
	if (!outFile)
	{
		outFile.close();
		return 0;
	}
	int x;
	while (inFile >> x)
		arr[num++] = x;
	for (int i = num - 1; i >= 0; i--)
		outFile << arr[i] << " ";
	inFile.close();
	outFile.close();
	return 0;
}

18.4 reading and writing of binary files

  • Storing information by text is not only a waste of space, but also not easy to retrieve.
  • In binary files, information occupies sizeof (object name) bytes; The number of bytes occupied by class member data in text file is different, and the occupied space is generally larger than that of binary.

ostream::write member function: ostream & write (char * buffer, int count);

class Person
{
public:
	char m_name[20];
	int m_age;
};
int main()
{

	Person p;
	ofstream outFile("o.bin", ios::out | ios::binary);
	while (cin >> p.m_name >> p.m_age)
		outFile.write((char*)&p, sizeof(p));//Cast type
	outFile.close();
	//heiren hot cry  
	return 0;
}

istream::read member function: istream & read (char * buffer, int count);

Person p;
ifstream inFile("o.bin", ios::in | ios::binary); //Binary read mode on
if (!inFile)
	return 0;//fail to open file
while (inFile.read((char *)&p, sizeof(p)))
	cout << p.m_name << " " << p.m_age << endl;
inFile.close();

put and get member functions of file stream class

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
    
    ifstream inFile("a.txt", ios::binary | ios::in); 
    if (!inFile)
        return 0;
    ofstream outFile("b.txt", ios::binary | ios::out);
    if (!outFile) 
    {
        inFile.close();
        return 0;
    }
    char c;
    while (inFile.get(c))  //Each character read
        outFile.put(c);  //Write a character
    outFile.close();
    inFile.close();
    return 0;
}

Reading and writing byte by byte is not as fast as reading and writing one memory area at a time. The number of bytes read and written each time should preferably be an integer multiple of 512

18.5 moving and obtaining file read-write pointers

  • I fstream class and fsstream class have seekg member function, which can set the position of file read pointer;
  • ofstream class and fsstream class have seekp member functions, which can set the position of the file write pointer.
  • I fstream and fsstream classes also have tellg member functions, which can return the position of the file read pointer;
  • ofstream and fsstream classes also have tellp member functions, which can return the position of the file write pointer.

Function prototype

ostream & seekp (int offset, int mode);
istream & seekg (int offset, int mode);
//There are three mode s: ios::beg - offset (> = 0) bytes from the beginning to the back ios::cur - current forward (< = 0) / rear (> = 0) offset bytes ios::end - offset bytes from the end to the front (< = 0)
int tellg();
int tellp();
//The seekg function locates the file read pointer to the end of the file, and then the tellg function obtains the position of the file read pointer, which is the file length

Take chestnuts for example: find the file in half, and name is equal to "Heiren"

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

class Person
{
public:
	char m_name[20];
	int m_age;
};
int main()
{


	Person p;
	ifstream ioFile("p.bin", ios::in | ios::out);//Open both read and write
	if (!ioFile) 
		return 0;
	ioFile.seekg(0, ios::end); //Locate the read pointer to the end of the file so that you can use tellg to get the file length later
	int L = 0, R; // L is the sequence number of the first record in the half search range
				  // R is the sequence number of the last record in the half search range
	R = ioFile.tellg() / sizeof(Person) - 1;
	do {
		int mid = (L + R) / 2; 
		ioFile.seekg(mid *sizeof(Person), ios::beg); 
		ioFile.read((char *)&p, sizeof(p));
		int tmp = strcmp(p.m_name, "Heiren");
		if (tmp == 0)
		{ 
			cout << p.m_name << " " << p.m_age;
			break;
		}
		else if (tmp > 0) 
			R = mid - 1;
		else  
			L = mid + 1;
	} while (L <= R);
	ioFile.close();

	system("pause");
	return 0;
}

18.6 differences between opening methods of text files and binary files

  • On UNIX/Linux platforms, there is no difference between opening files in text or binary mode.
  • On UNIX/Linux platforms, text files take \ n (ASCII code 0x0a) as line feed symbols; On the Windows platform, text files use the concatenated \ r\n (\ r's ASCII code is 0x0d) as the newline symbol.
  • On Windows platform, if the file is opened in text mode, when reading the file, the system will convert all \ R \ nin the file into one character. If two consecutive bytes in the file are 0x0d0a, the system will discard the first 0x0D byte and only read 0x0a. When a file is written, the system converts \ n to \ r\n write.

It is always safest to open a file in binary mode.

19 generics and templates

  • Generic programming is an algorithm that does not specify the type of data to be operated when it is implemented. It means that the algorithm can be applied to a variety of data types as long as it is implemented once. Its advantage lies in code reuse and reducing repeated code writing.
  • Templates are the basis of generics and the blueprint or formula for creating generic classes or functions.

19.1 function template

General form of function template:

template<class T>or template<typename T>
Function type function name(parameter list)
{
	Function body;
}
template<class T1,class T2,...>//class can be replaced by typename
 Function type function name(parameter list)
{
	Function body;
}
//Take a chestnut
template<class T> T max(T a, T b)
{
	return a > b ? a : b;
}
int main()
{
	cout <<"max value is "<< max(12,34) << endl;//34
	cout << "max value is " << max(12.4, 13.6) << endl;//13.6
	cout << "max value is " << max(12.4, 13) << endl;//error there is no instance of function template "max" matching the parameter list. The parameter type is: (double, int)
	return 0;
}

19.2 type formwork

  • After declaring the class template, you can use type parameters for class member functions and member variables. In other words, the built-in types such as int, float and char can be replaced by type parameters.
    General form of class template:
template<class T>//class can be replaced by typename template header
class Class name
{
	Function definition;
};
//Multiple type parameters are similar to function templates, separated by commas

When a member function in a class is defined outside the class declaration, it must be defined as a function template with a template header. The definition form is as follows:

template<class T>//class can be replaced by typename
 Function type class name<T>::Function name(parameter list )
{
	Function body;
}

For example, chestnuts:

template<typename T1, typename T2>  // Template header has no semicolon
class Point {
public:
	Point(T1 x, T2 y) : x(x), y(y) { }
public:
	T1 getX() const;  //Add const after the member function to declare that the value of the member variable will not be changed inside the function
	void setX(T1 x);  
	T2 getY() const;  
	void setY(T2 y);  
private:
	T1 x;  
	T2 y;  
};
template<typename T1, typename T2>  //Template head
T1 Point<T1, T2>::getX() const  {
	return x;
}
template<typename T1, typename T2>
void Point<T1, T2>::setX(T1 x) {
	x = x;
}
template<typename T1, typename T2>
T2 Point<T1, T2>::getY() const {
	return y;
}
template<typename T1, typename T2>
void Point<T1, T2>::setY(T2 y) {
	y = y;
}
int main()
{
	Point<int, double> p1(66, 20.5);
	Point<int, char*> p2(10, "33 degrees east longitude");
	Point<char*, char*> *p3 = new Point<char*, char*>("12 degrees west longitude", "66 degrees north latitude");
	cout << "x=" << p1.getX() << ", y=" << p1.getY() << endl;
	cout << "x=" << p2.getX() << ", y=" << p2.getY() << endl;
	cout << "x=" << p3->getX() << ", y=" << p3->getY() << endl;
	return 0;
}

19.3 difference between typename and class

After c + + was introduced into the template, class was used to define the template parameter type. Later, in order to avoid confusion caused by the use of class declaration class and template, the keyword typename was introduced.

  • The keyword class and typename in the template definition syntax work exactly the same.
  • The difference is that typename has another function: using nested dependent name
class MyClass
{
public:
		typedef int LengthType;
		LengthType getLength() const
		{
			return this->length;
		}
		void setLength(LengthType length)
		{
			this->length = length;
		}
		
private:
	LengthType length;
};
template<class T>
void MyMethod(T myclass)
{
	//Tell the c + + compiler that the string after typename is a type name, not a member function or member variable
	typedef typename T::LengthType LengthType; //
	LengthType length = myclass.getLength();
	cout << "length = " <<length<< endl;
	
}
int main()
{
	MyClass my;
	my.setLength(666);
	MyMethod(my);//length = 666
	return 0;
}

19.4 the trickiness of strong and weak typed languages and c + + templates

Computer programming languages can be divided into strongly typed languages and weakly typed languages according to "whether to explicitly indicate the data type when defining variables".

  • Strongly typed language - when defining a variable, you need to explicitly specify the data type. After specifying a data type for the variable, you can't assign other types of data, unless you go through forced type conversion or implicit type conversion. Typical strongly typed languages include C/C + +, Java, c# and so on.
int a = 123;  //No conversion
a = 12.89;  //Implicit conversion 12 (rounding off decimal parts)
a = (int)"heiren,HelloWorld";  //Cast (get the address of the string) cast between different types needs to be cast
//Java has more strict requirements for type conversion than C/C + +. Implicit conversion is only allowed from low to high, and conversion from high to low must be forced.
int a = 100;  //No conversion
a = (int)12.34;  //Cast (directly rounding off the decimal part to get 12)
  • Weakly typed language - there is no need to explicitly specify the data type when defining a variable. The compiler (interpreter) will automatically deduce the type according to the data assigned to the variable, and can assign different types of data to the variable. Typical weakly typed languages include JavaScript, Python, PHP, Ruby, Shell, Perl, etc.
var a = 100;  //Assign to integer
a = 12.34;  //Assign to decimal
a = "heiren,HelloWorld";  //Assign to string
a = new Array("JavaScript","React","JSON");  //Assign to array

**        Strongly typed language can detect whether the operation of a variable is correct during compilation, because the type of variable is always determined, which speeds up the operation of the program; For weakly typed languages, the type of variables can be changed at any time. The compiler can determine the type of variables during compilation. The current type of variables can be determined only after the program runs and assignment. Therefore, traditional compilation is of little significance to weakly typed languages**

  • Interpretative languages - weak types are often interpretative languages that compile while executing
  • Compiled language - compile before execute.

Strongly typed languages are more rigorous, and many errors can be found during compilation. They are suitable for developing large-scale, system level and industrial projects; The weakly typed language is more flexible, with high coding efficiency, easy deployment and low learning cost. In addition, the IDE of strongly typed language is generally strong, with good code perception and rich prompt information; Weakly typed languages usually write code directly in the editor.

The power source of C + + template exit is the encapsulation of data structure: data structure focuses on data storage and its addition, deletion, modification and query. C + + developers want to encapsulate these structures, but the types of data components in these structures cannot be predicted in advance, so the template was born.

STL(Standard Template Library) is the name after c + + encapsulates the data structure.

20 namespace and exception handling

20.1 namespace

A namespace is actually a memory area named by the user. The user can specify a named space area as needed. Each namespace has a scope. Putting some global entities in the namespace is separated from other global entities.
General form of namespace definition:

namespace [Namespace name]//When the name is omitted, it represents an unnamed namespace
{
	namespace member ;
}

References to namespace members: namespace name:: namespace member name
Use namespace alias: namespace alias = namespace name
Format for declaring namespace members using using: using namespace name:: namespace member name;
Use using to declare all members of the namespace: using namespace namespace name;

  • After using declaration, when using the namespace member in the scope where the using statement is located, it does not need to be qualified with the namespace name.
  • All identifiers of the standard C + + library, including functions, classes, objects, and class templates, are defined in a namespace called std.
  • Nameless namespace, valid only within the scope of this file.

20.2 exception handling

Exceptions are errors caused by changes in the use environment and user operations during the execution of the program, which affect the operation of the program.

  • Common errors in the program: syntax errors, running errors
  • The composition of exception handling mechanism: check exception (try), throw exception (throw), catch and handle exception (CATCH)

Exception handling statement:

  • The checked statement must be placed in {} after try, otherwise it will not work and {} cannot be omitted.
  • The statement for exception handling must be placed in {} after catch. The exception information type in () after catch cannot be omitted, and the variable name can be omitted.
  • catch statement block cannot be used alone. It must appear as a whole with try statement block.
  • In the try catch structure, there can only be one try, but there can be multiple catches
  • catch(...) is usually placed last and can catch any type of exception information.
try
{
	The statement being checked (there can be more than one) throw Statement);
}
catch(Exception information type [Variable name])
{
 
}

throw statement: how variable or expression;

  • throw is placed in the try and can also be used alone. Look for try catch from the upper function. If it is not found, the system will call the system function terminate to terminate the program.
try
{
	throw 123;
}
catch (int a)
{
	cout << a << endl;//123
}

There is no finally in c + +
Class exception handling. When a class object is defined in the try, the object created before throwing an exception in the try will be automatically released.
Exception specification - describes the types of exceptions that a function is allowed to throw.

  • Exception specifications should appear in both function declarations and function definitions.
  • If there is no exception specification, you can throw any type of exception.
    General form of exception specification: function type, function name (parameter type) throw ([exception type 1, exception type 2,...])
float fun(float float)throw(int,float,double);

C + + standard exception

abnormaldescribe
std::exceptionThis exception is the parent of all standard C + + exceptions.
std::bad_allocThis exception can be thrown through new.
std::bad_castThe exception can be passed through dynamic_cast throw.
std::bad_exceptionThis is useful when dealing with unexpected exceptions in C + + programs.
std::bad_typeidThis exception can be thrown through typeid.
std::logic_errorIn theory, exceptions can be detected by reading the code.
std::domain_errorThis exception is thrown when an invalid mathematical field is used.
std::invalid_argumentThis exception is thrown when an invalid parameter is used.
std::length_errorThis exception is thrown when too long std::string is created.
std::out_of_rangeThis exception can be thrown through methods, such as std::vector and STD:: BitSet < >:: operator.
std::runtime_errorExceptions that cannot theoretically be detected by reading code.
std::overflow_errorThis exception is thrown when a math overflow occurs.
std::range_errorThis exception is thrown when an attempt is made to store a value that is out of range.
std::underflow_errorThis exception is thrown when a mathematical underflow occurs.

21 STL

C + + Standard Template Library (STL) is the most successful example of generic programming. STL is a collection of templates for some common data structures and algorithms. It was developed under the auspices of Alex Stepanov and joined the C + + standard in 1998.

  • The core of C + + standard template library includes three components: container, algorithm and iterator

21.1 containers

Sequential container: variable length dynamic array Vector, double ended queue deque, bidirectional linked list
Associated containers: set, multliset, map, multimap

  • The elements in the associated container are sorted, so it has very good performance when searching.
    Container adaptation: stack, queue, priority_queue
    All containers have the following functions:
int size();
bool empty();

Sequential container and associated container functions:

begin()
end()
rbegin()
erase(...)
clear()

Functions unique to sequential containers:

front()
back()
push_back();
pop_back();
insert(...);

21.2 iterators

An iterator is a data type that checks the elements in a container and traverses the elements. C + + tends to use iterators rather than subscript operations, because the standard library defines an iterator type for each standard container (such as vector), and only a few containers (such as vector) support subscript operations to access container elements. By definition, it can be divided into the following four types.
1. Forward iterator: container class name:: iterator iterator name;
2. Constant forward iterator: container class name:: const_iterator iterator name;
3. Reverse iterator: container class name:: reverse_iterator iterator name;
4. Constant reverse iterator: container class name:: const_reverse_iterator iterator name

21.3 algorithm

STL provides algorithms that can be used in various containers (about 70 kinds), such as insertion, deletion, search, sorting, etc. The algorithm is the function template. The algorithm manipulates the elements in the container through iterators.
     Most common algorithms in STL are defined in the header file algorithm. In addition, there are some algorithms in the header file numeric.
     Many algorithms operate on an interval on the container (or the whole container), so two parameters are required, one is the iterator of the starting element of the interval, and the other is the iterator of the next element after the end element of the interval.
Will change the container it acts on. For example:

  • Copy: copy the contents of one container to another.
  • remove: deletes an element from the container.
  • random_shuffle: randomly shuffle the elements in the container.
  • fill: fills the container with a value.

Does not change the container it acts on. For example:

  • Find: find elements in the container.
  • count_if: count the number of elements that meet certain conditions in the container.
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
int main()  {
   vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4); //1,2,3,4
	vector<int>::iterator p;
	p = find(v.begin(), v.end(), 3); //Find 3 in V. if it cannot be found, find returns v.end()
	if (p != v.end())
		cout << "1) " << *p << endl; //eureka
	p = find(v.begin(), v.end(), 9);
	if (p == v.end())
		cout << "not found " << endl; //Can't find

	p = find(v.begin() + 1, v.end() - 1, 4); //Find 4 in the two elements 2 and 3
	cout << "2) " << *p << endl; //Not found, pointing to the next element 4

	int arr[10] = { 10,20,30,40 };
	int * pp = find(arr, arr + 4, 20);
	if (pp == arr + 4)
		cout << "not found" << endl;
	else
		cout << "3) " << *pp << endl;
	return 0;

}

22 summary

Finally finished, because COVID-19 has been quarantined for more than a month at home. It took about a week. This article is oriented to the basic knowledge of C + +, and there are many detailed and deep ones that are not written in. Later, I will write articles on templates, STL, C++11 new features, Boost library, etc. I just started to write a blog. If there are errors or missing knowledge points in the article, please point out them.

Keywords: C++

Added by neptun on Thu, 07 Oct 2021 21:18:17 +0300