Isn't there some serious problem in learning C++? A slightly crazy grammatically confusing version of the note and a slightly long wordless title make people question Neo's mental state.

1. Basic syntax of C++

type conversion

Never mix unsigned and signed types
. When both are included in an expression, the signed type will be converted to the unsigned type, and unexpected results will occur when the value is negative;

unsigned a = 1; int b = -1; cout<<a*b;//输出 4294967295
//详解: b的源码:100...1 负数转补码按位取反加1后为:1111...0  无符号类型把该值读出为4294967295 (结果视所在机器位数而定)

When using unsigned types for loops, pay attention to the fact that they will never be less than 0.

Escape sequences and specified types

Insert image description here
Insert image description here
Note: "\1234" The first 3 constitute the octal corresponding asill value of the escape sequence

Insert image description here
Note: Use L instead of lowercase l when representing long integer type. It is easily confused with 1;

The suffix exists to clearly indicate the data type of the literal value, thereby avoiding implicit type conversion or ambiguity by the compiler. However, not all data types require a suffix since their type can be automatically inferred from the form of the literal. Additionally, using the wrong suffix can lead to compilation errors or runtime errors, so it needs to be used with care. Speechless;

Insert image description here

(a) 字符  宽字符型字符(wchar_t类型)  字符串  宽字符型字符串
(b) 整数  无符号数  长整数  无符号长整数  八进制数  十六进制数
(c) 浮点型   单精度浮点型   long double类型的扩展精度浮点型 
(d) 整数  无符号整数 浮点数  科学计数法表示的浮点数

Variable initialization is not equal to assignment (initialization is to create a variable and assign an initial value, assignment is to erase the current value and replace it with a new value). The variable declaration
specifies the variable type and name. In addition to the definition , it also applies for storage space, and may also Assign initial value. (It is recommended to initialize each variable of the built-in type)

extern int i; //声明 i 
int j;//声明并定义 j
extern int k = 3; //赋初始值抵消了extern的作用变成了定义,且如果是在函数内部初始化extern标记的变量会报错

A variable must and can only be defined once in a file. The variable used in other files must be declared, but it must not be defined repeatedly! (A variable can and can only be defined once, but can be declared multiple times)

The naming convention for identifiers
consists of letters, numbers, and underscores, and must start with a letter or underscore.
Unable to specify identifier

  • Some keywords used in C++ language, such as if, int, false, etc.
  • Some reserved words in the C++ standard library cannot be underlined twice in a row, or underlined starting with a capital letter.
  • Identifiers defined outside a function cannot begin with an underscore.

Recommended identifier specifications

  • Know the meaning after seeing the name, can reflect the actual meaning and be easy to understand
  • Lowercase letters in variable names, such as index
  • The class name starts with a capital letter, such as Index
  • Identifiers consisting of multiple letters should be separated by underscores or starting with a capital letter, such as student_loan_up or studentLoanUp.

Scope
Global scope and block
scope are nested. The outer scope declares a name, and its nested scope, that is, the inner scope, can access the name, and the inner scope is allowed to redefine the outer scope. The domain already has a name.

Key Differences between References and Pointers

  1. References must be initialized when they are created (pointers can be initialized at any time).
  2. There cannot be NULL references, and the references must be associated with legal storage locations (pointers can be NULL).
  3. Once a reference is initialized, the reference relationship cannot be changed (a pointer can change the object it refers to at any time).

https://www.runoob.com/w3cnote/cpp-difference-between-pointers-and-references.html

Using uninitialized pointers can easily lead to errors, so it is not known whether it is initialized to nullptr when pointing to a specific object, such as: int *p = nullptr; therefore, to determine
whether a pointer points to a legal address, just determine whether it is nullptr, or if it is not initialized For pointers, you can try...catch whether there is an error.

void* is a special pointer type that can store the address of any object.

The problem with int* p and int *p is that p, whose basic type is int, is a pointer to int; so it is recommended to use the second writing method, int *p1, *p2;

A pointer to a pointer needs to be dereferenced twice in order to access the original object;
a reference to a pointer, the reference itself is not an object so a pointer to a reference cannot be defined, but the pointer is an object, so there is a reference to the pointer;

int i = 33;
int *p;//int 类型的指针p
int *&r = p;//从右往左看,r 是 对指针p的引用
r = &i;//r是指向p的引用,给r赋值&i 就是让p指向i
*r = 0;//解引用 r 得到 i,也就是p指向的对象,改i的值为0

When faced with complex pointer or reference declaration statements, reading from right to left can help clarify the true meaning;

The way to define a const variable and declare it in multiple files is to add the extern keyword whether it is defined or declared;

extern const int bufsize = fcn();//1.cc定义并初始化一个常量,并让该常量能被其他文件访问

** Bottom-level const and top-level const? **

Constant expression: an expression whose value will not change and the calculation result can be obtained during compilation.
For example, const staff_size = get_size(); is not, because it cannot be obtained until runtime. Const int limit = 20; is a constant expression.

C++11: If you determine that a variable is a constant expression, declare it as a constexpr type;

Auto type derivation
1. When using a reference as the initial value, use the type of the reference object as the type of auto;
int i = 0, &r = i;
auto a = r; //a type is int
2. auto will ignore the top-level const, Keep the underlying const;
auto &h = 42; //Non-const reference needs to be bound to a modifiable object;
const auto &j = 42;

Everything should be made as simple as possible, but not simpler

Class is the abstract and collective name of objects, and objects are instances of classes;

Shallow copy: only copies the pointer address, C++ default copy
constructor and assignment operator overloading are shallow copies;
saves space, but easily causes multiple releases;
deep copy: reallocates heap memory and copies
the content pointed by the pointer.
Wastes space but does not result in multiple releases;

copy on write

2. C++ pointers

Uninitialized and illegal pointers, you must be very careful when using pointer indirection to ensure that they are initialized and assigned properly!
1. If you don’t know where it points to at first or when it is not used, you can initialize it to null.
2. Before making an indirect reference to a pointer, determine whether the value of the pointer is null;

int *a;//未初始化化
*a = 12//非法访问

If you are lucky, you locate an illegal address, and the program terminates with an error. If you are not lucky, you locate an accessible address and modify it. The error is difficult to catch, and the error caused may be completely unexpected!

Lvalue and rvalue
Insert image description here
The left side of = sign is lvalue, and the right side of = sign is rvalue. The left value takes the memory space at cp+1 as shown above, and the right value takes the value of the memory space;

char ch = 'a';
char *cp = &ch;

Regarding ++++, ---- and other operators:
The way the compiler program is decomposed into symbols is: read character by character.
If the character may form a symbol, then read the next character until the read The entered characters
no longer form a meaningful symbol. This process is called the "greedy method".
For example: int a=1,b=2;c;
c=a+++b;/∥ is equivalent to a+++b
d=a++++b;/∥ is equivalent to af+++b,error

Insert image description here
Storage of code and data in C++ programs;

Insert image description here
Insert image description here

RAlI (Resource Acquisition Is Initialization) :
A resource management method unique to C++. A few other languages, such as Rust, have also adopted RAII, but among the mainstream programming languages, C++ is the only one that relies on RAII for resource management. RAlI relies on stacks and destructors to manage all resources, including heap memory.
The use of RAll enables C++ to effectively manage memory without requiring a garbage collection method similar to Java. The existence of RAll is also the main reason why although garbage collection can theoretically be used in C++, it has never really become popular.
RAll has some relatively mature smart pointer representatives: such as std:auto_ptr and boost:shared_ptr

Insert image description here

Memory leak (Memory Leak) problem
What is a memory leak problem:
It refers to the dynamically allocated heap memory in the program that is not released or cannot be released for some reason,
resulting in a waste of system memory, causing the program to slow down or even system crash. as a result of.
Causes and troubleshooting methods of memory leaks:
1. Memory leaks mainly occur in the heap memory allocation method, that is, "after the memory is configured, all pointers pointing
to the memory are lost." Without a garbage collection mechanism like the language, such memory
slices cannot be returned to the system.
2. Because memory leaks are problems during program running and cannot be identified through compilation, they can
only be identified and diagnosed during program running.

Four commonly used smart pointers are introduced in C++:
unique_ptr, shared_ptr, weak_ptr;
auto_ptr: deprecated in C++11 and officially deleted in C++17;

Insert image description here

Insert image description here
Usage issues
Insert image description here
Ownership issues
Insert image description here
Circular references: Reference counting brings circular reference issues, causing the heap memory to be unable to be recycled normally, causing memory leaks.

Insert image description here

C++ reference
Insert image description here

For basic types in functions, pass by value is more efficient, and for custom types, pass by reference to const is more efficient;

Eliminate "wild" pointers.
Pointers pointing to "junk" memory. If and other judgments do not work for them because NULL is not set;
generally there are three situations:
1. Pointer variables are not initialized;
2. Pointers that have been released and unused are not set to NULL, such as pointers after delete and free;
3. Pointer operations exceed The scope of the variable;

Notes on the use of pointers: Please set the value to NULL for
uninitialized, unused or out-of-range pointers . (It’s difficult, pointers are used in multiple places, and it’s hard to determine when they are no longer needed. Solution: smart pointers)

The null pointer is a pointer to null and is used for memory initialization pointer variables. The memory number 0~255 is the memory occupied by the system and is inaccessible; the
wild pointer is a pointer pointing to an illegal memory space. Both accesses should report an error, but running under Dev is as follows Code: It compiles correctly and can still run, but there is no output. The window automatically closes after running for a period of time. Why is this?

#include <bits/stdc++.h>

using namespace std;

int main(){
    
    
	int a = 10;
	int *p = NULL;
	cout << *p <<endl;
	
	int *q = (int *)0x1110;
	cout << *q <<endl;
	return 0;
}

Although the syntax is correct and can pass the compiler, due to memory access violations caused by dereferencing null pointers and wild pointers, the operating system terminates the execution of the program to protect the system.

Insert image description here
The real storage method of the machine: positive numbers are stored directly, and negative numbers retain the sign bit and invert the bitwise +1;
big endian is commonly used on the Internet and conforms to human reading habits, and little endian is used by most personal PCs and conforms to the machine;

Insert image description here

Insert image description here
This is very important and must be noted! ! !
Insert image description here
The sdshdr structure designed in Redis has a len variable to store the string length, which does not need to be traversed to calculate; there is a free to manage the remaining capacity. If the capacity is not enough, it will automatically expand and modify the len size;

pointers and references

Insert image description here

Array of pointers, each one in this array is a pointer. T *t[ ]
array pointer (a pointer to an array), this pointer points to an array. T (*t) [ ]

Insert image description here
In the third example, first look at the left char of the first const modification, which means that the value of the pointer cannot be changed, and then look at the second const modification of *, which means that the pointer's pointing cannot be changed;

There are three situations when const modified pointers

  1. const modified pointer - constant pointer (the pointer pointed to can be changed, but the value pointed to cannot be changed)
  2. const modified constant - pointer constant (pointer pointer cannot be changed, pointer value can be changed)
  3. const modifies pointers and constants (neither can be changed)

Look at whether the right side of const is a pointer or a constant. If it is a pointer, it is a constant pointer. If it is a constant, it is a pointer constant.

const is often used to prevent misuse

smart pointer

The memory in the heap area must be released manually, otherwise memory leaks will occur;

Solution: Smart pointers are class templates. Create a smart pointer object on the stack, hand the ordinary pointer to the smart pointer object, and when the smart pointer object expires, call the destructor to release the memory of the ordinary pointer.

unique_ptr: the object pointed to exclusively
shared_ptr:
wear_ptr:

Insert image description here

Insert image description here

Insert image description here

Insert image description here
Insert image description here

Insert image description here

3. C++STL library

The relationship between the six major components of the stl library
Insert image description here

Insert image description here

container

Containers are used to store data;
STL containers are divided into two categories:
Sequence Containers:
the elements in them are all sortable (ordered). STL provides vector, list, deque and other sequence containers, while stack ,queue,priority_queue is the container adapter;
Associative Containers:
Each data element is composed of a key (key) and a value (Value). When the element is inserted into the container, press its key in some way. Specific rules are placed in the appropriate location; common STL associated containers such as: set, multiset, map, multimap;

#include <bits/stdc++.h>

using namespace std;

struct Display{
    
    
	void operator()(int i){
    
    
		cout << i << " ";
	}
};

int main(){
    
    
	int arr[4] = {
    
     1, 2, 3, 4};
	vector<int> vec(arr, arr+4);//动态数组 
	list<int> lis(arr, arr+4);//链表 
	deque<int> deq(arr, arr+4);//双端队列
	queue<int> que(deq);//队列 
	stack<int> sta(deq);//栈 
	priority_queue<int> prique(arr, arr+4);//优先队列 
	
	for_each(vec.begin(), vec.end(), Display());
	for_each(deq.begin(), deq.end(), [](int i){
    
    
		cout<< i << " ";
	});
	
	while(!que.empty()){
    
    
		cout << que.front() << " ";
		que.pop();
	}
	while(!sta.empty()){
    
    
		cout << sta.top() << " ";
		sta.pop();
	}

	cout<<endl;
	map<string, int> studentlevel;
	studentlevel["level1"] = 1;
	studentlevel["..."] = 3;
	studentlevel["level6"] = 6;
	studentlevel.insert(pair<string, int>("level4", 4));
	for_each(studentlevel.begin(), studentlevel.end(), [](pair<string, int> i){
    
    
		cout<<i.first<<":"<<i.second<<endl; 
	});
	
	map<string, int>::iterator iter = studentlevel.find("level6");
	if(iter != studentlevel.end()){
    
    
		cout<<"level6 超能力者人数:"<<iter->second<<endl; 
	}
	
	return 0;
}

**Very important to note: **Beware of iterator failure issues, such as iter = studentlevel.earse(''cc''); delete the value with key cc and return the iterator at the next position; (*it)
. empty(); simplified it->empty();

For any loop body that uses an iterator, do not add elements to the container to which the iterator belongs;
for example, push_back may cause the iterator of the vector object to become invalid;
for example, a range for loop adds elements to the vector.

functor

  • Functors are generally not used alone, mainly for use with STL algorithms.
  • Function pointers cannot meet the abstraction requirements of STL, cannot meet the requirements of software building blocks, and cannot be matched with other components of STL;
  • The essence is that the class overloads an operator() and creates an object that behaves like a function.

From function pointer->generics->functor->functor template; lazy

bool MySort(int a, int b){
    
    
	return a ‹ b;
}

void Display(int a){
    
    
	cout << a <<" ";
}

int main(){
    
    
	//C++方式
	int arr[] = {
    
    4,3, 2, 1,7};
	sort(arr, arr + 5, MySort);
	for_each(arr, arr + 5, Display);

}

If the data type changes, many functions need to be overloaded, which is too troublesome, so generics came out

template<class T>
bool MySort(T const& a, T const& b){
    
    
	return a ‹ b;
}

template<class T>
void Display(T const& a){
    
    
	cout << a <<" ";
}

int main(){
    
    
	//C++泛型
	int arr[] = {
    
    4,3, 2, 1,7};
	sort(arr, arr + 5, MySort<int>);
	for_each(arr, arr + 5, Display<int>);
}

Then there is the functor


struct mySort{
    
    
	bool operator()(int a, int b){
    
    
		return a ‹ b;
	}
}

struct Display{
    
    
	void Display(int a){
    
    
		cout << a <<" ";
	}
}

int main(){
    
    
	//C++仿函数
	int arr[] = {
    
    4,3, 2, 1,7};
	sort(arr, arr + 5, mySort());
	for_each(arr, arr + 5, Display());
}

Next is the functor template. The basic type does not need to be added, but it can be added if the object consumption is relatively large.

template<class T>
struct mySort{
    
    
	bool operator()(T const&  a, T const&  b){
    
    
		return a ‹ b;
	}
}

template<class T>
struct Display{
    
    
	void Display(T const&  a){
    
    
		cout << a <<" ";
	}
}

int main(){
    
    
	//C++仿函数
	int arr[] = {
    
    4,3, 2, 1,7};
	sort(arr, arr + 5, mySort<int>();
	for_each(arr, arr + 5, Display<int>();
}

Algorithm

Algorithms in STL are roughly divided into four categories: included in,,
1. Non-variable sequence algorithms: refers to algorithms that do not directly modify the contents of the containers they operate;
2. Variable sequence algorithms: refers to those that can modify the contents of the containers they operate. Algorithms;
3. Sorting algorithms: including algorithms for sorting and merging sequences, search algorithms, and set operations on ordered sequences;
4. Numerical algorithms: performing numerical calculations on container contents;
the most common algorithms include:
search, sorting And general algorithms, permutation and combination algorithms, numerical algorithms, set algorithms and other algorithms

transform(); container calculation function; count statistical function; binary_search(); binary search;

int main(){
    
    
	int arr[] = {
    
    1, 1, 1, 2, 2, 3, 4, 5, 5, 6};//父序列 
	vector<int> zi(arr+2, arr+6); //子序列 
	int len = sizeof(arr)/sizeof(arr[0]);
	cout << count(arr, arr+len, 1) << endl; 
	cout << count_if(arr, arr+len, bind2nd(less<int>(), 4)) << endl; 
	cout << binary_search(arr, arr + len, 6)<<endl;
	cout<< *search(arr, arr+len, zi.begin(), zi.end()) << endl;
	return 0;
}

Implementation of full arrangement of handwriting

Enter a complete string without repeated characters and print out the complete arrangement of characters in the string
. For example, enter 123 = 3 2 1 = 3!
Output the total situation
123
132
213
231
312
321

#include <bits/stdc++.h>
//f(123)=1+f(23),f(23)=2+f(3),f(3)=3递归
using namespace std;

void swap(char*a, char *b){
    
    
	char tmp = *a;
	*a = *b;
	*b = tmp;
}

void permutation(char *ptr, char* postion){
    
    
	if(*postion == '\0'){
    
    //基准点,退出
		cout << ptr <<endl;
	}
	for (char* pChar = postion; *pChar != '\0'; pChar++){
    
    
		swap(*pChar, *postion);//依次和后面的字符交换,比如123,定1位,依次交换2,3
		permutation(ptr, postion + 1);//递归下去
		swap(*postion, *pChar);//别忘了换回来
	}
}

int main(){
    
    
	char test[] = "321";
	permutation(test, test);
	return 0;
}

The order of the array must be guaranteed. For example, next is from small to large. If you implement it yourself, you will not lose the arrangement. Prev is in order from large to small. The
full arrangement functions next_permutation() and prev_permutation() in stl;

sort
STL's sort algorithm
uses QuickSort (quick sort) when the amount of data is large, and merges and sorts by segments.
Once the amount of segmented data is less than a certain threshold (16), in order to avoid excessive extra load caused by the recursive call of QuickSort, InsertSort (insertion sort) is used instead.
If the recursion level is too deep, HeapSort (heap sort) will be used instead.

iterator

Similar to smart pointers, a small handwritten gc case uses the iterator method;

Open source code MyGC
Insert image description here

Int main0
GCPtr<int> p;
try{
    
    
p = new int;
catch (bad_alloc exc)X
cout << "Allocation failure!\n";
return 1;
3
*p =88;
*p+=1;
cout << "Value at p is:* << *p << endl;
GCPtr<int> p1 =p;
cout << "p's list size;: " << p.gclistSize() << endl;
p.showlist(0;
GCPtr<int, 10> pA = new int[10];
Iter<int> it = pA.beginO;
int index = 1;
for ( it != pA.end); it++)
7it = index++;

Insert image description here
The pointer pointing to the object contains a ref reference count, but uses a list to record the pointer, and releases all pointers on the list at the end to solve the circular reference problem.
Insert image description here

container adapter

stack stack:
a "first in first out" container, the underlying data structure is deque;
queue queue:
a "first in first out" container, the underlying data structure is deque;
priority_queue priority queue:
a special Queue, which can be sorted in the queue (heap sort), the underlying implementation structure is vector or deque;

priority queue

priority_queue<int> a;//默认大根堆,升序排列
priority_queue<int, vector<int>, greater<int>> b;//升序排列大根堆
priority_queue<int, vector<int>, less<int>> c;//降序排列小根堆

greater和less是仿函数,就是一个类中重载operator()的实现,类就有了类似函数的行为即仿函数,当涉及自定义类型当然可以自己重载;

struct cmp{
    
    
	bool operator(type a, type b){
    
    
		return a.x < b.x;//大顶堆
	}
}

space allocator

  • "STL Source Code Analysis" Hou Jie, SGI STL version is more readable;
  • From the perspective of usage, the allocator works silently hidden in other components and does not need to be cared about. However, from the perspective of understanding STL implementation, it is the component that needs to be analyzed first;
  • The analysis of allocator can reflect C++’s optimization ideas in performance and resource management;

STL Summary
The six major components of STL bring new polymorphism and reuse to software programming, and are the essence of modern C++ language efficiency; the
learning path of generics and STL is very steep, and it is recommended that beginners first learn basic usage and simple extensions;
After mastering a certain foundation, you can improve your capabilities by further studying and analyzing the source code and writing your own components;

Other libraries

boost library
Boost library is the general name for some C++ libraries that provide extensions to the C++ language standard library. It is developed and maintained by the Boost community organization. The Boost library can work perfectly with the C++ standard library and provide extended functions for it; the C++ standard library also Gradually absorbing some of its functions;
Boost can be roughly divided into more than 20 categories: string and text processing libraries, container libraries, algorithm libraries, function objects and high-order programming libraries, comprehensive class libraries, etc.;
official website: https:/ /www.boost.org/
Mirror: https://dl.bintray.com/boostorg/release/

Http application framework Drogon based on C++14/17 (the name of a dragon (Drogon) in "Game of Thrones"): https://github.com/drogonframework/drogon/blob/master/README.zh- CN.md

Chinese document translated by grpc: https://doc.oschina.net/grpc?t=58008 (cross-platform RPC framework), explanation: https://juejin.cn/post/7047885453336248327

Tencent's open source rpc framework phxrpc: https://gitee.com/mirrors/PhxRPC# https://gitee.com/link?target=https%3A%2F%2Fgithub.com%2FTencent%2Fphxrpc%2Fwiki
https:// github.com/Tencent/phxrpc

4. C++ design patterns

There are 23 common object-oriented and reusable design patterns in software that provide general solutions to some common problems based on previous experience.
Design patterns also have costs and applicable scenarios, but they are not omnipotent. These 23 types are actually suitable for scenarios that have strong scalability and will be used repeatedly in a large number of scenarios with some changes in the future;

Singleton pattern

Insert image description here

Observer pattern

Insert image description here
Implementation ideas:
decouple the responsibilities of the problem, abstract Observable and observer, and distinguish abstraction and entity;

class Observer
public:
	Observer();
	virtual ~Observer();
	//当被观察对象发生变化时,通知被观察者调用这个方法
	virtual void Update(void* pArg) = 0;
}

class User1:public Observer{
    
    
	virtual void Update(void* pArg)
	cout <<"User1 Got News:" << endl;
}

class User2 :public Observer{
    
    
	virtual void Update(void* pArg)
	cout <<"User2 Got News:" << endl;
}

What are void, NULL and nullptr?
void* is a general pointer type that can point to any type of data. It is not directly related to a specific data type, so it cannot be dereferenced and requires explicit type conversion to be used. For example:

void* ptr = nullptr; // ptr is a null pointer
int* intPtr = static_cast<int*>(ptr); // Convert void pointer to int pointer
In older C++ versions, NULL was defined as the integer 0. This means it can be used as a pointer to the null value. However, using the integer 0 may lead to some ambiguity, since 0 can also be a value of other integer types. In modern C++, it is recommended to use nullptr instead of NULL. For example:

int* ptr = nullptr; // ptr is a null pointer
nullptr is a keyword introduced in C++11 to represent a null pointer. nullptr has better type safety compared to NULL. It is implicitly convertible to any pointer type and cannot be confused with other integer types. For example:

int* ptr = nullptr; // ptr is a null pointer

A pointer is a variable used to store a memory address, and the data pointed to can be accessed through the dereference operator *. A null pointer means that the pointer does not point to any valid memory address. In C++, these concepts can be used to conveniently handle the situation where the pointer is null and avoid undefined behavior or errors.

Insert image description here
The 23 object-oriented design patterns are roughly classified into creative, structural and behavioral patterns;
design patterns are not omnipotent, they are based on system change points, and can be used wherever there are changes;
design patterns are decoupling and, In order to expand, it is usually evolved and needs evolution to be accurately
positioned;
design pattern is a software design method, not a standard. At present, most of the current frameworks already contain
a large number of design pattern ideas;

Generic programming

Insert image description here

If object-oriented is a method of calling functions through an indirect layer in exchange for an abstraction, then generic programming is a more direct abstraction, which does not lose efficiency because of the indirect layer; unlike object-oriented dynamic
polymorphism , Generic programming is a kind of static polymorphism, which generates the most direct code through the compiler at compile time;
generic programming can separate algorithms from specific types and structures, and reuse code as much as possible;

template<class T>
T max(T a, T b){
    
    
	return a > b ? a : b;
}

//特化
template<class T1, class T2>
int max(T1 a, T2 b){
    
    
	return static_cast<int>(a > b ? a : b);
}

int main(){
    
    
	cout << max(1, 3) << endl;
	cout << max(3.5, 1.5) << endl;
	cout << max('a', 'b') << endl;

	cout << max(10, 3.5) << endl;
}

The compiler will instantiate a corresponding template function instance based on the actual parameter types passed to the function.

The relationship between generics, polymorphism and overloading: Generics can improve the reusability of code, but it does not directly involve the concepts of polymorphism or overloading. Polymorphism refers to the feature that allows objects of different classes to respond to the same message, while overloading refers to allowing multiple functions with the same name but different parameter lists in the same scope. Although generics can improve code reusability, they do not directly affect these concepts.

This example demonstrates generics. The max function does not need to repeatedly change types. Instead, the compiler generates function calls based on the passed parameters and templates. However, if the generic function does not meet our needs, it needs to be specialized . .You can interrupt the debugging to see which function is running.

Once a mistake is made in generic programming, it is difficult for beginners to correct it! Because the compiler does a lot of things automatically;

functional programming;

static_cast

Insert image description here

//C++ const转ẽ
const int a = 10;
//int* pA = &a;
int* pA = const_cast<int*>(&a);
*pA = 100:
cout<<a<<endl;可能任然是10,内存模型问题
return O;

Insert image description here

adapter pattern

Reuse the functions of the original code, do not change and then create new functions.
Multiple inheritance is very bad. It has something to do with C++,
diamond inheritance problems, and virtual inheritance.

The first: use multiple inheritance.
The second: use combination to instantiate objects of the original class as member variables of the new class.

Guess you like

Origin blog.csdn.net/BinBinCome/article/details/131736702
Recommended