I. concept of templates
Template is to establish a general mold, which greatly improves the reusability
Another programming idea of C + + is called generic programming, which mainly uses template
C + + improves two template mechanisms: function template and class template
Two, template characteristics
- The template cannot be used directly. It is just a framework
- The universality of templates is not everything
3, Function template
Function template function: create a general function whose return value type and formal parameter type can be represented by a virtual type without specifying
1. Grammar
template<typename T> Function declaration or definition
Template -- declare the creation of a template
typename -- indicates that the symbol behind it is a data structure, which can be replaced by class
T -- General data type, the name can be replaced, usually in uppercase letters
Sample code
template<typename T> //Declare a template and tell the compiler not to report an error for the T immediately following the code. T is a general data type void Myswap(T& a, T& b) { T temp = a; a = b; b = temp; } int main() { int a = 10, b = 50; cout << a << " " << b << endl; Myswap(a, b); //1. Automatic type derivation cout << a << " " << b << endl; Myswap<int>(a, b);//2. Displays the specified type }
2. Precautions
For automatic type derivation, a consistent data type T must be derived before it can be used
The template can be used only after the data type of T is determined
3. Differences between ordinary functions and function templates
- Automatic type conversion (implicit type conversion) can occur when ordinary function calls
- When a function template is called, if automatic type derivation occurs, implicit type conversion will not occur
- Implicit type conversion can occur if the specified type is displayed
4. Call rules for ordinary functions and function templates
- If both ordinary functions and function templates can be implemented, call ordinary functions first
- You can force a function template to be called through an empty template parameter list
void Myswap(T& a, T& b) { cout << "Template called!" << endl; T temp = a; a = b; b = temp; } void Myswap(int& a, int& b) { cout << "function called!" << endl; int temp = a; a = b; b = temp; } int main() { int a = 20, b = 10; cout << a << " " << b << endl; Myswap<>(a, b);//You can force a function template to be called through an empty template parameter list cout << a << " " << b << endl; return 0; }
- Function templates can also be overloaded
- If the function template can match better, call the function template first
template<class T> void Myswap(T& a, T& b) { cout << "Template called!" << endl; T temp = a; a = b; b = temp; } void Myswap(char& a, char& b) { cout << "function called!" << endl; int temp = a; a = b; b = temp; } int main() { int a = 20, b = 10; cout << a << " " << b << endl; Myswap(a, b);//Function templates can produce better matches cout << a << " " << b << endl; return 0; }
Summary: since the function template is provided, it is better not to provide ordinary functions, otherwise ambiguity may occur
4, Class template
Class template function:
Establish a general class. The member data types in the class can be represented by a virtual type without specific formulation
1. Grammar
template<typename T> class
Template -- declare the creation of a template
typename -- indicates that the symbol behind it is a data structure, which can be replaced by class
T -- General data type, the name can be replaced, usually in uppercase letters
Code example
template<class NameType,class AgeType> class Person { public: NameType name; AgeType age; Person(NameType name, AgeType age) { this->name = name; this->age = age; } }; int main() { Person<string,int> p1("yxc", 18); //Type must be declared }
2. Difference between class template and function template
There are two main differences between class templates and function templates:
- Class templates do not use automatic type derivation
- Class templates can have parameter constructs in the template parameter list
template<class NameType,class AgeType = int> //You can specify the type in the parameter list class Person { public: NameType name; AgeType age; Person(NameType name, AgeType age) { this->name = name; this->age = age; } void ShowInfo() { cout << "Name: " << name << " Age:" << age << endl; } }; int main() { Person<string> p1("yxc", 18); //When specified, it does not need to be declared in the argument list p1.ShowInfo(); return 0; }
5, Limitations of templates
The versatility of templates is not everything
- The generalization of user-defined types can be solved by using specific templates
- Learning templates is not to write templates, but to use the templates provided by the system in STL
6, Creation time of member function in class template
The member function in the class template is created only when it is called
7, Class template object as function parameter
Three incoming modes
- Specify the type passed in -- directly display the data type of the object
- Parameter instantiation -- change the parameters in the object into templates for transfer
- Whole class templating -- passing this object type Templating
void ShowInfo1(Person<string,int>&p) //1. Specify incoming type { cout << "Name: " << p.name << " Age:" << p.age << endl; } template<class T1,class T2> //2. Parameter Templating void ShowInfo2(Person<T1,T2>&p) { cout << "Name: " << p.name << " Age:" << p.age << endl; cout << "T1 The type of is" << typeid(T1).name() << " T2 The type of is" << typeid(T2).name() << endl; } template<class T> void ShowInfo3(T& p) //3. Template the whole object { cout << "Name: " << p.name << " Age:" << p.age << endl; cout << "T The type of is" << typeid(p).name() << endl; }
8, Class template and inheritance
When class templates encounter inheritance, you should pay attention to the following points:
- When the parent class inherited by a subclass is a class template, the subclass shall specify the type of T in the parent class when declaring
- If not specified, the compiler cannot allocate memory to subclasses
- If you want to flexibly specify the type of T in the parent class, the child class also needs to become a class template
template<class T> class Base { public: T m; }; class Son :public Base<int> //The type of T must be specified before it can be assigned to a subclass { public: Son() { cout << typeid(m).name() << endl; } }; //If you want to flexibly specify the T type in the parent class, the subclass also needs to change the class template template<class T1,class T2> class Son2 :public Base<T1> { public: T2 obj; Son2() { cout << typeid(this->m).name() << " " << typeid(obj).name() << endl; } }; int main() { Son s1; Son2<char,int> s; return 0; }
9, Class template member function out of class implementation
When the class template member function is implemented outside the class, the template parameter list needs to be added
template<class T1,class T2> class Person { public: T1 name; T2 age; Person(T1 name, T2 age); void showPerson(); }; template<class T1,class T2> Person<T1,T2>::Person(T1 name, T2 age)//Outside class implementation of constructor of template class { this->name = name; this->age = age; } template<class T1,class T2> void Person<T1, T2>::showPerson() //The member function of the template class is implemented outside the class { cout << this->name << " " << this->age << endl; }
10, Class template is written in files
Problem: the creation time of the member function in the class template is in the calling stage, resulting in the link failure when writing the file
solve
Include directly cpp source file
Write the declaration and implementation to the same file and change the suffix to hpp, hpp is the name of the contract, not mandatory
The first solution: directly include the cpp header file
The second solution is to cpp and h write the contents together and change the suffix to hpp file
11, Class templates and friends
Implementation within the class of global functions - just declare friends within the class and implement them (more often used)
Out of class implementation of global functions - the compiler needs to know the existence of global functions in advance
template<class T1,class T2> //Let the compiler guide the existence of the Person class in advance class Person; template<class T1, class T2>//Let the compiler know the existence of global functions in advance void showPerson(Person<T1, T2>& p) { cout << p.name << " " << p.age << endl; } template<class T1, class T2> class Person { friend void showPerson<>(Person<T1,T2>& p); //The global function is implemented outside the class. As a friend of the class template, you need to add an empty template parameter list private: T1 name; T2 age; public: Person(T1 name, T2 age); }; template<class T1, class T2> Person<T1, T2>::Person(T1 name, T2 age)//Outside class implementation of constructor of template class { this->name = name; this->age = age; } int main() { Person<string,int> p1("yxc", 18); showPerson(p1); return 0; }