This chapter will describe some specific STL template ideas, and briefly describe the operator overloading and the linkage of the template .
Templates are important concepts in the C + + language. It provides a common way to develop reusable code, that is, to create parameterized C + + types. There are two types of templates: function templates and class templates. The use of function templates is similar to the use of C + + preprocessor, which provides the ability to replace text in the process of compiling code, but the function template can also protect the type in some way. You can use class templates to write generic, type-safe classes.
1. Write a function template that sums the elements of an array.
#include <iostream>using namespace std;/*int sum (int data[],int nsize) { int sum=0; for (int i=0;i<nsize;i++) { sum+=data[i]; } return sum;} */template <class t>t sum (t data[],int nsize) { T sum=0; for (int i=0;i<nsize;i++) { sum+=data[i]; } return sum;} int main () { int data1[]={1,2,3,4,5}; Float data2[]={1.1,2.2,3.3,4.4,5.5}; Double data3[]={1.1,2.2,3.3,4.4,5.5}; Cout<<sum (data1,5) <<endl<<sum (data2,5) <<endl<<sum (data3,5); return 0;}
Note that the code in the int array of the function, change it to the lower template function, only need to abstract the data type, using Template<class name> instead of the original variable, you can implement the template function, the type of the function should also be changed to name.
This function has been able to achieve the sum of the different basic data types, if further thinking, I hope that the function can be used to implement the linked list, set and other elements of the summation, which is the way of thinking of STL.
In addition, when used in the template, the class keyword can be replaced with TypeName, that is, Template<typename name>.
2. Write the template class of dynamic array, realize the idea of STL vector writing.
#include <iostream>using namespace Std;template <class t>//a simple template class, only constructors, destructors, add element functions, but has been able to describe the characteristics of the template class. Class Myarray{private:int m_ntotalsize; Array total length int m_nvalidsize; The effective length of the array, that is, the current number of elements T * M_PDATA; Data pointer public://constructor MyArray (int nsize=2)//Assuming the default array length is 2 {m_pdata=new t[nsize]; M_ntotalsize=nsize; m_nvalidsize=0; }//get array valid length int getvalidsize () {return m_nvalidsize; }//Gets the total length of the array int gettotalsize () {return m_ntotalsize; }//Returns a position element T Get (int pos) {return m_pdata[pos]; }//Add an element void Add (T value) {if (m_nvalidsize<m_ntotalsize)//If the array is not full {M_pdata[m_n Validsize]=value; m_nvalidsize++; } else//array dynamically increases the array size at full time {T * polddata=m_pdata; Save current data pointer m_pdata=new t[m_ntotalsize*2]; Original array space size expanded twice times for (int i=0;i<m_ntotalsize;i++)//copy original data { M_pdata[i]=polddata[i]; } m_ntotalsize*=2; Current array total length update delete polddata; Frees the memory M_pdata[m_nvalidsize]=value used by the old array; Add new element m_nvalidsize++; Update array Validity}}//destructor virtual ~myarray () { if (m_pdata!=null) &NB Sp { Delete []m_pdata; m_pdata=null; } }};int Main () {myarray<int> array1; cout<< "Array total length:" <<array1. Gettotalsize () << "Array valid length:" <<array1. Getvalidsize () <<endl; Array1. ADD (1); Array1. ADD (2); Array1. ADD (3); cout<< "Array total length:" <<array1. Gettotalsize () << "Array valid length:" <<array1. Getvalidsize () <<endl; Cout<<array1. Get (0) << "" <<array1. Get (1) << "" <<array1. Get (2) <<endl; Myarray<double> array2; cout<< "Array total length:" <<array2. Gettotalsize () << "Array valid length:" <<array2.GetValidSize () <<endl; Array2. ADD (1.1); Array2. ADD (2.2); Array2. ADD (3.3); cout<< "Array total length:" <<array2. Gettotalsize () << "Array valid length:" <<array2. Getvalidsize () <<endl; Cout<<array2. Get (0) << "" <<array2. Get (1) << "" <<array2. Get (2) <<endl; return 0;}The template class simulates a simplified, vector-like dynamic array and implements the add element function. You can see that the array class default array size is 2, when 3 elements are inserted, the array size dynamically increases to twice times the original, which is also the implementation of the vector. Although the array dynamic size is implemented, it is necessary to make a copy of the original data of the array, so there is a loss of efficiency at this time.
The use of int and double classes is demonstrated in the program, which shows the meaning of the abstract of template function, that is, the reuse of code can be realized.
This class can reflect the STL container about memory "memory allocation, destruction, redistribution" idea, that is, the memory management of the part of the further abstraction, programming system code, the application does not have to understand the process of memory changes, with expert-written code, rather than write their own code to manage memory. STL is the inevitable result of the development of ordinary template class, not a new technology.
3.traits TechnologySTL Standard Template Library emphasizes the reuse of software, and traits technology is an important means. Traits's Chinese meaning is the feature, traits like the feature extractor, extracts the characteristics of different classes, in order to be able to work together, traits relies on
explicit template specialization to drag out fragments of code that vary in type, using a unified interface to package. This interface can contain anything that a C + + class can contain, such as inline types, member functions, and member variables. As the client's template code, it can be accessed indirectly through the interface exposed by the traits template class. The following is a simple example to understand.
The known shaped array class Intarray with the floating-point array floatarray, the array and the product of a number.
The code written in the normal way is as follows: (Red is the difference between two array classes)
#include <iostream>using namespace Std;class intarray{private:int a[10];p Ublic:intarray () {for (int i=0;i&l t;10;i++) {a[i]=i+1; }}//The function outputs the sum of all elements and times of the product int Calculate (int times) {int sum=0; for (int i=0;i<10;i++) {sum+=a[i]; } return sum * times; }};class floatarray{private:float a[10];p Ublic:floatarray () {for (int i=0;i<10;i++) { a[i]=i+1; }}//This function outputs the sum of all elements and times of float Calculate (float times) {int sum=0; for (int i=0;i<10;i++) {sum+=a[i]; } return sum * times; }};int Main () {Intarray A; Floatarray F; cout<< "shaped array and twice times is:" <<a.calculate (2) <<endl; cout<< "floating-point array and 2.2 times times is:" <<f.calculate (2.1) <<endl;}
It can be found that the Calculate function of the two array classes is the same as the parameter type, the return value type is different, the other is the same, then can the interface function of a class to complete the above function? Yes, of course you need to use the template. An Array of classes is added here.
Template<class t>class array{public: float Calculate (T &t,float times) { return t.calculate ( times); }};
and the main function needs to be changed:
int main () { intarray A; Floatarray F; Array<intarray> A1; Array<floatarray> A2; cout<< "shaped array and twice times is:" <<A1. Calculate (a,2) <<endl; cout<< "floating-point array and 2.2 times times is:" <<a2. Calculate (f,2.1) <<endl;}
The array interface function is used here to manipulate the array and floating-point array classes. But a careful analysis will reveal that the details are still problematic. For example, the parameters and return values of the Calculate () function in Intarray are of type int, the parameters and return values of the Calculate () function in Floatarray are of type float, and the Calculate () function in the template class Array The parameters and return values are fixed for the float type, although it seems to be correct from the results of the program, but not strict enough, when the program is very complex point of error, then how to solve the output, output parameter type difference? Traits technology is a good solution, and the steps are as follows.
Step One: Define the basic template classTemplate<class t>
Class Numtraits
{
};
The Numtraits class can write nothing, just stating that it is a template class.
Step Two: template specificity. template<>
Class numtraits<intarray>
{
Public
typedef int INPUTTYPE;
typedef int RESULTTYPE;
};
Template<>
Class numtraits<floatarray>
{
Public
typedef int INPUTTYPE;
typedef int RESULTTYPE;
};
It can be seen that the corresponding template-specific classes only use typedef redefinition functions, Intarray and Floatarray two array classes Calculate () function parameter type, return value type redefined to InputType and Resulttype, for writing a template class to make preparations for the common invocation interface.
Step Three: Unified template calling Class authoringTemplate<class t>
Class Array
{
Public
TypeName Numtraits<t>::resulttype Calculate (T &t,typename numtraits<t>::inputtype times)
{
Return t.calculate (times);
}
};
The purpose of the TypeName keyword here is to tell the compiler that Numtraits<t>::resulttype and Numtraits<t>::inputtype are a type and not a variable.
At first glance, the Calculate () function of the Array class is somewhat difficult to understand. When the template parameter represents Intarray, the definition changes to the following code:
TypeName Numtraits<intarray>::resulttype Calculate (T &t,typename Numtraits<intarray>::inputtype Times
According to the definition of template specificity in (2), Numtraits<intarray>::resulttype represents Int,numtraits<intarray>::inputtype also represents int, so the above definition becomes int Calculate (T &t,int times). When the template parameter represents Floattype the situation is similar here do not repeat.
Therefore, the parameter type and return value type of the Calculate () function in the Array class is variable and varies with the template parameters. Therefore, it is important to define typedef for the input and output parameters in a template-specific class, and the corresponding names will be the same.
Finally, the definition of the Calculate () function in the Array class looks cumbersome, again using the TypeDef definition to make it clear:
Template<class t>
Class Array
{
Public
typedef typename NUMTRAITS<T>::RESULTTYPE Result;
typedef typename NUMTRAITS<T>::INPUTTYPE Input;
Result Calculate (T &t,input times)
{
Return t.calculate (times);
}
};
Finally, give the complete code:
#include <iostream>using namespace Std;class intarray{private:int a[10];p Ublic:intarray () {for (in T i=0;i<10;i++) {a[i]=i+1; }}//The function outputs the sum of all elements and times of the product int Calculate (int times) {int sum=0; for (int i=0;i<10;i++) {sum+=a[i]; } return sum * times; }};class floatarray{private:float a[10];p Ublic:floatarray () {for (int i=0;i<10;i++) { a[i]=i+1; }}//This function outputs the sum of all elements and times of float Calculate (float times) {int sum=0; for (int i=0;i<10;i++) {sum+=a[i]; } return sum * times; }};//Basic template class Template<class T>class numtraits{};//template Special Template<>class numtraits<intarray>{public: typedef int INPUTTYPE; typedef int RESULTTYPE;};/ /template Special Template<>class numtraits<floatarray>{public:typedef float inputtype; typedef float RESULTTYPE;};/ /Unified Template Calling Class writing TempLate<class T>class Array{public:typedef TypeName Numtraits<t>::resulttype result; typedef typename NUMTRAITS<T>::INPUTTYPE Input; Result Calculate (T &t,input times) {return t.calculate (times); }};int Main () {Intarray A; Floatarray F; Array<intarray> A1; Array<floatarray> A2; cout<< "shaped array and twice times is:" <<A1. Calculate (a,2) <<endl; cout<< "floating-point array and 2.2 times times is:" <<a2. Calculate (f,2.1) <<endl; return 0;}4. Templates and operator overloadingFor example, when you have a template function for size comparison, the following code is available:
#include <iostream>using namespace std;template <class u,class v>bool grater (U const &U,V const &V) { C3/>return U>v;} int main () { cout<<grater (2,1) <<endl; Cout<<grater (2.2,1.1) <<endl; Cout<<grater (' A ', ten) <<endl; return 0;}
The template function is perfectly correct when comparing the base type, but when you or V have a representation class that cannot be compared, you need to overload the operator at this point.
Suppose there is a student class:
Class Student{private: char name[20]; int grade;public: Student (char name[],int grade) { strcpy (this->name,name); this->grade=grade; } BOOL Operator> (const int &value) const { return this->grade>value; }};
To compare whether his score is greater than 99, when using Grater (s,99), you need to overload the ">" Operator of the Student class, as shown in the code below:
BOOL Operator> (const int &value) const
{
Return this->grade>value;
}
It is now possible to compare the Student class with the int type.
The complete template and overloaded operator functions are as follows:
#include <iostream> #include <string.h>using namespace Std;class student{private: char name[20]; int grade;public: Student (char name[],int grade) { strcpy (this->name,name); this->grade=grade; } BOOL Operator> (const int &value) const { return this->grade>value; }}; Template <class u,class v>bool grater (U const &U,V const &v) { return u>v;} int main () { Student s ("Raito", +); Cout<<grater (s,99) <<endl; return 0;}
Because the STL has a large number of template functions, it is often necessary to overload the corresponding operators. A template function is equivalent to an application framework that has been written, and operator overloading is equivalent to invoking an interface.
C + + STL Basics and Applications (2) template and operator overloading