3. STL程式設計三
阿新 • • 發佈:2018-11-21
1. 演算法容器的使用:
#include <iostream> #include <functional> #include <vector> #include <algorithm> //演算法,共包含108個演算法 #include <numeric> //整數 using namespace std; using namespace std::placeholders; //用於bind()函式的"_1"引數 struct MyStruct { int operator()(int data) //對()進行過載-->偽函式 { return data % 2 == 1; } }; int get(int data) { return data % 2 == 1; } struct my { int get(int data) { return data % 2 == 1; } }; int main() { vector<int> myint{ 1,2,3,4,5,6,7,8,9,11 }; //建立容器 //法一:lambda表示式 int num1 = count_if(myint.begin(), myint.end(), [](intdata)->bool {return data % 2 == 0; }); //偶數個數 //法二:偽函式(匿名物件) int num2 = count_if(myint.begin(), myint.end(), MyStruct()); //MyStruct()匿名物件 //法三:有名物件 MyStruct my1; int num3 = count_if(myint.begin(), myint.end(), my1); //法四:函式 int num4 = count_if(myint.begin(), myint.end(), get); //法五:成員函式(函式繫結器) my my2; auto fun = bind(&my::get, &my2, _1); int num5 = count_if(myint.begin(), myint.end(), fun); cout << num1 << endl; //4 cout << num2 << endl; //6 cout << num3 << endl; //6 cout << num4 << endl; //6 cout << num5 << endl; //6 system("pause"); return 0; }
1.1 加入函式模板如下:
#include <iostream> #include <functional> #include <vector> #include <algorithm> //演算法,共包含108個演算法 #include <numeric> //整數 using namespace std; using namespace std::placeholders; //用於bind()函式的"_1"引數 template<class T> bool getT(T data) { return data % 2 == 1; } int main() { vector<int> myint{ 1,2,3,4,5,6,7,8,9,11 }; //建立容器 int num6 = count_if(myint.begin(), myint.end(), getT<int>); cout << num6 << endl; //6 system("pause"); return 0; }
2. 模板的展開 ==> 屬於模板元的範疇
#include <iostream> #include <cstdarg> using namespace std; template<class T> void show(T t) { cout << t << " "; } template<class...Args> void all(Args...args) { int arr[] = { (show(args),0)... }; //使用陣列進行展開 } template<class...Args> void allIt(Args...args) { int arr[] = { (show(args),0)... }; //int arr[],用來約束展開多少層,儲存在數組裡面,[]不能省 } int main() { all(1, 2, 3, 4, 5); cout << endl; all(1, 2, 3, 4, 5, 6, 7, 8); cout << endl; allIt(1, 'A', "123", 7.89); cout << endl; system("pause"); return 0; }
3. 函式模板推理機制:
#include <iostream> using namespace std; template<typename T> void go(T t) //將型別泛型 { cout << typeid(T).name() << endl; //cout << t << endl; cout << "T:" << endl; } template<int i> //模板之間也可以過載 void go() //資料可以為任意資料(相當於數字模板) { cout << i << endl; } template<typename T> void go(T *t) //將型別泛型 { cout << typeid(T).name() << endl; cout << "T *:" << t << endl; } int main() { /* go(31 - 2); //呼叫泛型函式模板 go<31 - 2>(); //呼叫數字模板 go<decltype(10 + 2)>(1234); //呼叫泛型函式模板,可以用decltype獲取資料型別 */ go(nullptr); //nullptr不是指標型別,是一種自定義的資料型別表示空指標而已,呼叫go(T t) int *p = nullptr; //呼叫go(T *t) go(p); system("pause"); return 0; }
4. 函式指標與函式模板:
4.1 函式模板賦值給函式指標:
#include <iostream> using namespace std; template<class T> void show(T t) { cout << t << endl; } struct MyStruct { template<class T> void show(T t) { cout << t << endl; } void go() { show(123); } }; //函式模板賦值給函式指標 int main() { //void(*p)() = show<int>; //無法從“void (__cdecl *)(T)”轉換為“void (__cdecl *)(void)” void(*p1)(int i) = show<int>; void(*p2)(double db) = show<double>; system("pause"); return 0; }
4.2 如何呼叫結構體中的函式模板?
//如何呼叫結構體中的函式模板? int main() { MyStruct my1; my1.go(); //結構體內部呼叫結構體中的函式模板 my1.show(12.3); //外部直接呼叫結構體中的函式模板 my1.show('A'); my1.show<int>('A'); system("pause"); return 0; }
4.3 如何繫結結構體內部的函式模板?
#include <iostream> #include <functional> using namespace std; using namespace std::placeholders; template<class T> void show(T t) { cout << t << endl; } struct MyStruct { template<class T> void show(T t) { cout << t << endl; } template<class T> void showit(T t1, T t2) { cout << t1 << " " << t2 << endl; } void go() { show(123); } }; //如何繫結結構體內部的函式模板? int main() { MyStruct my1; auto fun = bind(&MyStruct::showit<int>, &my1, 1, 2); fun(2); system("pause"); return 0; }
5. 函式模板、模板函式與類模板:
5.1 什麼是函式模板?什麼是模板函式?
函式模板就是上面所講的函式模板,而模板函式則是例項化的函式模板。
#include <iostream> using namespace std; /*函式模板,不呼叫不編譯*/ template<class T> T add(T a, T b) { return a + b; } int main() { add(1, 2); /*模板函式,也就是例項化的函式模板,自動根據引數推理*/ add<double>(1, 1.2); /*模板函式*/ system("pause"); return 0; }
5.2 類成員函式模板:
#include <iostream> using namespace std; class myclass { public: template<class T> //類成員函式模板 T add(T a, T b) { return a + b; } template<class T> //靜態函式模板 static T sub(T a, T b) { return a - b; } }; int main() { myclass *p = nullptr; int num1 = p->add<int>(2, 3); //強行指定的模板函式,當做類成員函式呼叫 int num2 = p->add(2, 3); //自動推理的模板函式 cout << num1 << endl; cout << num2 << endl; int num3 = myclass::sub(9 , 1); cout << num3 << endl; system("pause"); return 0; }
6. 模板在類中的應用:
#include <iostream> #include <cstdlib> using namespace std; class myclass { public: template<class T> T add(T a) { return a; } template<class T> T add(T a,T b) { show(); //函式模板與類成員函式可以互相呼叫 return a + b; } template<class T> T add(T a, T b,T c) { return a + b + c; } //template<class T> //virtual T add(T a, T b,T c) //error C2898: “T myclass::add(T,T,T)”: 成員函式模板不能是虛擬的 //{ // return a + b + c; //} void show() { cout << add<int>(10) << endl; //指明型別的方式呼叫 } }; int main() { myclass *p = nullptr; p->add(1, 2); system("pause"); return 0; }
7. 類模板與函式模板對比:
#include <iostream> #include <initializer_list> #include <memory> #include <string> using namespace std; template<class T,int n> class myarray { T *p; public: myarray(initializer_list<T> mylist) { p = new T[n]; //開闢記憶體 memset(p, 0, sizeof(T)*n); //記憶體清0 int length = mylist.size(); if (length > n) { abort(); //觸發異常 } else { int i = 0; for (auto j : mylist) //資料填充 { p[i] = j; i++; } } } ~myarray() { delete[] p; } void show() //顯示資料 { for (int i = 0; i < n; i++) { cout << p[i] << " "; } cout << endl; } void sort() //氣泡排序 { for (int i = 0; i < n - 1; i++) { for (int j = 0; j < n - 1 - i; j++) { if (p[j] < p[j+1]) //從大到小 { T temp = p[j]; p[j] = p[j + 1]; p[j + 1] = temp; } } } } }; int main() { myarray<int, 10> my1 = { 1,2,3,4,5,6,7,8,9 }; my1.show(); my1.sort(); my1.show(); myarray<double, 5> my2 = { 1.1,2.2,3.3,4.4,5.5 }; my2.show(); my2.sort(); my2.show(); myarray<string, 5> my3 = { "123","abcdef","sdaf","hello" }; my3.show(); my3.sort(); my3.show(); system("pause"); return 0; }
8. 類包裝器:
#include <iostream> using namespace std; template<class T,class F> //函式模板 T run(T t, F f) { return f(t); } class fun { public: double operator ()(double data) { return data - 10; } }; template<class T> //類模板 class Tfun { public: T operator ()(T data) { return data - 10; } }; int main() { cout << run(10.9, fun()) << endl; //fun()是匿名物件 fun x; cout << run(10.9, x) << endl; //x是有名物件 cout << run(10.9, Tfun<double>()) << endl; //模板函式的匿名物件,建構函式返回的就是匿名物件 Tfun<double> fang; cout << run(10.9, fang) << endl; system("pause"); return 0; }
9. 高階類包裝器:
#include <iostream> #include <list> #include <vector> using namespace std; template<class T, class F> //函式模板 T run(T t, F f) { return f(t); } template<class T> //類模板 class Trun { public: T operator ()(T data) { for (auto i:data) { cout << i <<" "; } cout << endl; return data; } }; int main() { list<int> myint; //構建連結串列,壓入資料 for (int i = 0; i < 5; i++) { myint.push_back(i); } run(myint, //lambda表示式 [](list<int> myint)->list<int> { for (auto i : myint) { cout << i << endl; } return myint; } ); system("pause"); return 0; }
#include <iostream> #include <list> #include <vector> using namespace std; template<class T, class F> //函式模板 T run(T t, F f) { return f(t); } template<class T> //類模板 class Trun { public: T operator ()(T data) { for (auto i:data) { cout << i <<" "; } cout << endl; return data; } }; int main() { vector<int> myv{ 1,2,3,4,5,7,8 }; run(myv, Trun< vector<int> >()); //匿名物件,用完就扔 run(myv, Trun< decltype(myv) >()); system("pause"); return 0; }
10. 類模板間的封裝、繼承、多型:
10.1 父類為類模板,子類也是類模板:
#include <iostream> using namespace std; //類模板支援封裝、繼承、多型 template<class T> class Tfu { public: T t; Tfu():t(0) { } void show() { cout << t << endl; } virtual void go() { cout << "fu:" << t << endl; } }; template<class T> class Tzi :public Tfu<T> { public: void go() { cout << "zi:" << t << endl; } }; int main() { Tzi<int> tzi; tzi.t = 109; tzi.show(); Tfu<int> *p = new Tzi<int>; //實現多型 p->go(); system("pause"); return 0; }
10.2 父類為類模板,子類為普通類:
#include <iostream> using namespace std; template<class T> class Tfu { public: T t; Tfu() :t(0) { } void show() { cout << t << endl; } virtual void go() { cout << "fu:" << t << endl; } }; class zi :public Tfu<int> { public: void go() { cout << "zi:" << t << endl; } }; int main() { zi z1; z1.t = 108; z1.show(); Tfu<int> *p = new zi; //多型 此處只能用int p->go(); system("pause"); return 0; }
10.3 父類為普通類,子類為類模板:
#include <iostream> using namespace std; //類模板支援封裝、繼承、多型 //T T //類模板 可以實現封裝、繼承、多型 //T P //類模板與類 可以實現封裝、繼承、多型 必須明確型別 //P T //類與類模板 可以實現封裝、繼承、多型 必須明確型別 多型什麼型別都可以 //P P //普通類 可以實現封裝、繼承、多型 class die { public: int t; die() :t(0) { } void show() { cout << t << endl; } virtual void go() { cout << "fu: " << t << endl; } }; template<class T> class er :public die { public: void go() { cout << typeid(T).name() << " zi: " << t << endl; } }; int main() { er<double> boer; boer.show(); die *p1 = new er<char>; die *p2 = new er<int>; die *p3 = new er<double>; p1->go(); p2->go(); p3->go(); system("pause"); return 0; }