When declaring variables, functions, and most other types of entities, C + + requires that we use the specified type. However, there is a lot of code that looks the same except for different types, such as the following example:
BOOL IsEqual (int left, int. right) {return left = = right;} BOOL IsEqual (const string& left, const string& right) {return left = = right;} void Test () {string S1 ("S1"), S2 ("S2"); Cout<<isequal (S1, S2) <<endl; Cout<<isequal (<<endl);
The above example is an overloaded function to compare the equality of two variables. These two functions have the same function, only the parameter types are handled differently, if you need to deal with float,double, and so on a series of types, you have to one by one write these types of overloaded functions, so the code is very cumbersome, then you need to use a template function to deal with, The template function only needs to write one to deal with the above problem.
Template<typename t>bool isequal (const t& left, const t& right) {return left = = right;} void Test1 () {string S1 ("S1"), S2 ("S2"); Cout<<isequal (S1, S2) <<endl; Cout<<isequal (<<endl);
When you compile a template function, the compiler automatically pushes the template parameter type according to the parameters passed in, and automatically generates the corresponding code, so that the amount of code is greatly reduced relative to the use of the function overload above, because the compiler will help you to push the code accordingly.
When working with the Left,right type above, the template function needs to be handled as follows:
Template <typename t>bool isequal (const t& left, const t& right) {return left = = right;} void Test2 () {cout<<isequal (<<endl;) Cout<<isequal (1,1.2) <<endl; Template parameter Mismatch cout<<isequal<int> (1,1.2) << Endl; Display instantiation cout<<isequal<double> (1,1.2) << Endl; Show instantiation}
Then we know that using the template function is to pay attention to the template parameter matching problem, you can also use the display instantiation method, forcing to handle the occurrence of this situation. If you want to compare two different types, you need to overload the function template so that it can accept two types, the following is the overload:
BOOL IsEqual (const int& left, const int& right) {return left = = right;} Template <typename t>bool isequal (const t& left, const t& right) {return left = = right;} Template <typename T1, typename T2>bool isequal (const t1& left, const t2& right) {return left = = right; }void test3 () {cout<<isequal (<<endl;) Cout<<isequal<int> (<< Endl); Cout<<isequal (1,1.2) <<endl;}
Template class
/* Format of template class */template<class name1, Class name2, ... class Namen>class name{...};
In the past, when processing a sequential table, to change the data type in it, often by modifying the typedef INT DataType to modify its storage type, you can now use the template class to not need to manually modify its type, the following is the use of template class implementation order table:
#include <string> #include <cassert>using namespace std;template <class t>class seqlist{public:seqlist (): _data (NULL), _size (0), _capacity (0) {cheakcapacity (); ~seqlist () {if (_data != null) {delete[] _data;}} Public:void pushback (const t& d) {cheakcapacity (); _data[_size] = d;_size++;} Void pushfront (const t& d) {cheakcapacity (); Int i = _size;for (i; i>0; i--) {_data[i] = _data[i-1];} _data[i] = d;_size++;} Void popback () {if (_size == 0) {cout<< "list is empty!!" <<endl;return;} _size--;} Void popfront () {int i = 0;if (_size == 0) {cout<< "List is empty!!" <<endl;return;} for (i; i<_size; i++) {_data[i] = _data[i+1];} _size--;} Public:void cheakcapacity () {if (_size == _capacity) {t* tmp = new t[_capacity +3];memcpy(tmp, _data, (_capacity) *sizeof (T));d elete[] _data;_data = tmp;_capacity = _capacity+3;}} Void display () {int i = 0;for (i; i<_size; i++) {cout<<_data[i]<< " ";} cout<< "Over" <<ENDL;} private:t* _data;int _size;int _capacity;}; Void test4 () { seqlist<int> l; l.pushback (1); l.pushback (2); l.pushback (3); l.pushback (4); l.pushback (5); l.display ();} Int main () { test4 (); system ("Pause"); return 0;}
Results:
650) this.width=650; "src=" Http://s4.51cto.com/wyfs02/M02/7E/83/wKioL1cDX-6j46f0AAAK6LcRYRY943.png "title=" t~}~ Wnyn) (1~q47p0]_ (pf4.png "alt=" Wkiol1cdx-6j46f0aaak6lcryry943.png "/>
When testing for the following TEST5 ():
void Test5 () {seqlist<string> L; L.pushback ("11111111111"); L.pushback ("21111111111"); L.pushback ("31111111111"); L.pushback ("41111111111"); L.pushback ("51111111111"); L.pushback ("61111111111"); L.display ();}
Results:
650) this.width=650; "src=" Http://s2.51cto.com/wyfs02/M01/7E/83/wKioL1cDYlKS2rMtAABXoC3TiEU193.png "title=" [b~$ Nr5_}~v ' R ' v{0]8%r_5.png "alt=" Wkiol1cdylks2rmtaabxoc3tieu193.png "/>
Why does it crash ?
Because when using memcpy (): When we are copying the basic type, we only use the data on the pointer passed by the copy, if it is a string type, we need to open up space on the heap, if the passed pointer is copied directly, It is possible (the implementation principle of the string type under VS is that if the string is not long, it is saved as an array, and if the string is too long, then the space on the heap is saved by the pointer), a common error such as two times of destruction occurs.
to solve the above problem, you should use the type extraction technique in C + + .
type extraction is a common programming technique that enables different types of data to implement different operations on the same function, unlike class encapsulation, where we don't know what type of object we're calling, Type extraction is a type that is known after compilation, implemented first, while the encapsulation of a class is defined by the type first and then implemented. Here we can use the special template to implement its programming ideas.
Again to implement the above order table:
#include <iostream> #include <string> #include <cassert>using namespace std;template <class t>class seqlist{public:seqlist (): _data (NULL), _size (0), _capacity (0) {cheakcapacity ();} ~seqlist () {if (_data != null) {delete[] _data;}} Public:void pushback (const t& d) {cheakcapacity (); _data[_size] = d;_size++;} Void pushfront (const t& d) {cheakcapacity (); Int i = _size;for (i; i>0; i--) {_data[i] = _data[i-1];} _data[i] = d;_size++;} Void popback () {if (_size == 0) {cout<< "list is empty!!" <<endl;return;} _size--;} Void popfront () {int i = 0;if (_size == 0) {cout<< "List is empty!!" <<endl;return;} for (i; i<_size; i++) {_data[i] = _data[i+1];} _size--;} Public:int find (const t& d) {int i = 0;for (i; i<_size; i++) {if (_data[i] == d) {return i;}} Return -1;} Void insert (int pos, const t& d) {cheakcapacity (); Int i = 0;for (i=_ size; i>pos; i--) {_data[i] = _data[i-1];} _data[pos] = d;_size++;} Void erase (Int pos) {assert (pos>0); assert (pos<_size); Int i = pos;for (i; i <_size; i++) {_data[i] = _data[i+1];} _size--;} Void sort () {int i,j;for (i=0; i<_size; i++) {for (j=0; j<_size-1-i; j++) {if (_ DATA[J]>_DATA[J+1]) {t tmp = _data[j];_data[j] = _data[j+1];_data[j+1] = tmp;}}}} Public:void cheakcapacity () {if (_size == _capacity) {t* tmp = new t[_capacity +3];if (Typetraits<t>::ispodtype (). Get ()) {memcpy (tmp, _data, (_capacity) *sizeof (T));} Else{for (int i=0; i<_size; i++) {tmp[i] = _data[i];}} Delete[] _data;_data = tmp;_capacity = _capacity+3;}} Void display () {int i = 0;for (i; i<_size; i++) {cout<<_data[i]<< " ";} cout<< "Over" <<ENDL;} private:t* _data;int _size;int _capacity;}; Struct falsetype{bool get () {return false;}}; Struct truetype{bool get () {return true;}}; template <class t>struct typetraits{typedef falsetype ispodtype;//Embedded Type};struct typetraits<char>{typedef truetype ispodtype;//Embedded Type};template<>struct typetraits<int>{typedef truetype ispodtype;//embedded Type};/* There are many basic types that do not appear to be written out, bool,float,double...*/ Void test6 () { seqlist<string> l; l.pushback (" 11111111111 "), l.pushback (" 21111111111 "); l.pushback (" 31111111111 "); l.pushback (" 41111111111 "); l.pushback (" 51111111111 "); l.pushback (" 61111111111 "); l.display ();} Int main () { test6 (); system ("Pause"); return 0;}
Results:
650) this.width=650; "src=" Http://s1.51cto.com/wyfs02/M01/7E/88/wKiom1cDcPSyEpOeAAAMW88CtqQ835.png "title=" Uk9akef0my147%zs1u756~k.png "alt=" Wkiom1cdcpsyepoeaaamw88ctqq835.png "/>
Template Summary
Advantages:
1. Template reuse code, save resources, faster iterative development, C + + Standard Template Library (STL) resulting.
2. Increase the flexibility of the code.
Disadvantages:
1. Templates make code messy, difficult to maintain, and time-coded to grow.
2. When a template compilation error occurs, the error message is very messy and difficult to locate errors.
Type Extraction Summary:
The type extraction technology can greatly accelerate the efficiency of the code, but also can make the idea become clearer.
If the above in the copy, actually do not memcpy () also can, as long as the object one copy, is also feasible, but the efficiency of the program will be greatly reduced.
In the commissioning of the time will make my thinking more clear.
This article is from the "Pzd Chuan Feng" blog, please make sure to keep this source http://xujiafan.blog.51cto.com/10778767/1760483
C++_ template class and type extraction technology