日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++模板的一些基础知识

發(fā)布時間:2024/7/23 c/c++ 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++模板的一些基础知识 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

一.函數(shù)模板

可看出就是將函數(shù)返回類型和形參類型去掉。

1.代碼1

#include <iostream> #include <vector> #include <string> #include <algorithm> #include <map> #include <fstream> using namespace std;template<typename T> void swap_(T& a, T& b ){T temp = a;a = b;b = temp; } int main() {//1.自動類型推導 必須要一致的數(shù)據(jù)類型才可用int a1 = 10, b1 = 20;cout<<a1<<" "<<b1<<endl;swap_(a1, b1);cout<<a1<<" "<<b1<<endl;float a2 = 10.01, b2 = 20.55;cout<<a2<<" "<<b2<<endl;swap_(a2, b2);cout<<a2<<" "<<b2<<endl;//2.顯示指定類型swap_<int>(a1, b1);cout<<a1<<" "<<b1<<endl;swap_<float>(a2, b2);cout<<a2<<" "<<b2<<endl;return 0; }

有兩種使用方式,一個是自動類型推導(必須要一致的數(shù)據(jù)類型才可用),一個是顯示指定類型。

2.代碼2

將類型作為參數(shù),用template修飾函數(shù)模板,解決不同類型函數(shù)但實現(xiàn)邏輯一樣的問題

#include <iostream> using namespace std;template <typename T>//函數(shù)模板 void display(T a) {cout<<"a:"<<a<<endl;cout<<"======="<<endl; }template <typename T,typename S>//函數(shù)模板 void display(T t, S s) { cout<<"t:"<<t<<endl;cout<<"s:"<<s<<endl;cout<<"======="<<endl; }template <typename T,int KSize>//函數(shù)模板 void display(T a) {for (int i=0;i<KSize;i++){cout<<"a:"<<a<<endl;}}int main() { display<int>(10);//模板函數(shù)display<double>(10.89);//模板函數(shù)display<int,float>(11,12.11);//模板函數(shù)display<int, 5>(11);return 0; }

3.代碼3

選擇排序,降序排序

#include <iostream> #include <vector> #include <string> #include <algorithm> #include <map> #include <fstream> using namespace std;template<typename T> void swap_(T& a, T& b){T temp = a;a = b;b = temp; }//從大到小排序 template<typename T> void sort_(T& arr){int n = sizeof(arr) / sizeof(arr[0]);for(int i = 0; i < n; i++){int index = i;for(int j = i + 1; j < n; j++){if(arr[index] < arr[j]){index = j;}}if(index != i){swap_(arr[index], arr[i]);}} } template <typename T> void printArr(T& arr){int n = sizeof(arr) / sizeof(arr[0]);for(int i = 0; i < n; i++ ){cout<<arr[i]<<" ";}cout<<endl; } int main() { // test06();char charArr[] = "bdfdsskn";sort_(charArr);printArr(charArr);int intArr[] = {6, 7, 4, 6, 8, 2, 3, 7};sort_(intArr);printArr(intArr);return 0; }

4.普通函數(shù)和模板函數(shù)的調用規(guī)則

4.1如果函數(shù)模板和普通函數(shù)都可以調用,優(yōu)先調用普通函數(shù)

#include <iostream> #include <vector> #include <string> #include <algorithm> #include <map> #include <fstream> using namespace std;// void myPrint(int a, int b){cout<<"調用的普通函數(shù)"<<endl; }template <typename T> void myPrint(T a, T b){cout<<"調用的函數(shù)模板"<<endl; } void test06(){int a = 10, b = 20;//如果函數(shù)模板和普通函數(shù)都可以調用,優(yōu)先調用普通函數(shù)myPrint(a, b); } int main() {test06();return 0; }

4.2通過空模板參數(shù)列表,強制調用函數(shù)模板

#include <iostream> #include <vector> #include <string> #include <algorithm> #include <map> #include <fstream> using namespace std;// void myPrint(int a, int b){cout<<"調用的普通函數(shù)"<<endl; }template <typename T> void myPrint(T a, T b){cout<<"調用的函數(shù)模板"<<endl; } void test06(){int a = 10, b = 20;// 通過空模板參數(shù)列表,強制調用函數(shù)模板myPrint<>(a, b); } int main() {test06();return 0; }

4.3重載函數(shù)模板

#include <iostream> #include <vector> #include <string> #include <algorithm> #include <map> #include <fstream> using namespace std;// void myPrint(int a, int b){cout<<"調用的普通函數(shù)"<<endl; }template <typename T> void myPrint(T a, T b){cout<<"調用的函數(shù)模板"<<endl; }template <typename T> void myPrint(T a, T b, T c){cout<<"調用的重載函數(shù)模板"<<endl; } void test06(){int a = 10, b = 20;// 通過 空模板參數(shù)列表,強制調用模板函數(shù)myPrint<>(a, b);myPrint<>(a, b, 100); } int main() {test06();return 0; }

4.4 如果函數(shù)模板能夠產(chǎn)生更好的匹配,優(yōu)先使用函數(shù)模板

#include <iostream> #include <vector> #include <string> #include <algorithm> #include <map> #include <fstream> using namespace std;// void myPrint(int a, int b){cout<<"調用的普通函數(shù)"<<endl;cout<<"a:"<<a<<endl;cout<<"b:"<<b<<endl; }template <typename T> void myPrint(T a, T b){cout<<"調用的函數(shù)模板"<<endl;cout<<"a:"<<a<<endl;cout<<"b:"<<b<<endl; }template <typename T> void myPrint(T a, T b, T c){cout<<"調用的重載函數(shù)模板"<<endl;cout<<"a:"<<a<<endl;cout<<"b:"<<b<<endl;cout<<"c:"<<c<<endl; } void test06(){int a = 10, b = 20;char c1 = 'a';char c2 = 'b';// 優(yōu)先將T推導為char 類型myPrint(c1, c2); } int main() {test06();return 0; }

可看出優(yōu)先將T轉換成char,而不是將char字符一個一個轉換成int類型。?

二.類模板

類模板語法和函數(shù)模板語法很接近,都是先聲明模板出來。

與函數(shù)模板差異

1.代碼1:

#include <iostream> #include <vector> #include <string> #include <algorithm> #include <map> #include <fstream> using namespace std;template <class NameType, class AgeType> class Person{ public:Person(NameType name, AgeType age){this->m_Name = name;this->m_Age = age;}void showPerson(){cout<<"name:"<<this->m_Name<<" age:"<<this->m_Age<<endl;}NameType m_Name;AgeType m_Age; };void test06(){Person<string, int> p1("lining", 13);p1.showPerson(); } int main() {test06();return 0; }

?

MyArray.h

#ifndef MYARRAY_H #define MYARRAY_H #include <iostream> using namespace std;template <typename T, int KSize, int KVal>//T就是要定義的類型class MyArray {public:MyArray();~MyArray(){delete []m_pArr;m_pArr=NULL;};void display();private:T *m_pArr; };template <typename T,int KSize, int KVal>//函數(shù)定義時 一定要寫 MyArray<T, KSize, KVal>::MyArray() {m_pArr = new T[KSize];for (int i=0;i<KSize;i++){m_pArr[i] = KVal;} }template <typename T,int KSize, int KVal>//函數(shù)定義時 一定要寫 void MyArray<T, KSize, KVal>::display() {for (int i=0;i<KSize;i++){cout<<"m_pArr[i]:"<<m_pArr[i]<<endl;} }#endif

demo.cpp

#include <iostream> #include <string> #include "MyArray.h" using namespace std;int main() { MyArray<int, 5, 6> arr;//每個元素都是6共5個元素的數(shù)組arr.display();return 0; }

?

2.與函數(shù)模板差異

1.類模板沒有自動推導方式

2.類模板中的參數(shù)列表可以有默認類型

#include <iostream> #include <vector> #include <string> #include <algorithm> #include <map> #include <fstream> using namespace std; //類模板中的參數(shù)列表可以有默認類型 template <class NameType, class AgeType = int> class Person{ public:Person(NameType name, AgeType age){this->m_Name = name;this->m_Age = age;}void showPerson(){cout<<"name:"<<this->m_Name<<" age:"<<this->m_Age<<endl;}NameType m_Name;AgeType m_Age; };void test06(){ // Person p1("lining", 13); //錯誤的 // Person<string, int> p2("lining", 13);Person<string> p2("lining", 13); //有默認類型所以這里可以省去intp2.showPerson(); } int main() {test06();return 0; }

3.類模板中成員函數(shù)和普通類成員函數(shù)創(chuàng)建方式

因為不知道是啥類型, 類模板中的成員函數(shù)在調用時才創(chuàng)建

#include <iostream> #include <vector> #include <string> #include <algorithm> #include <map> #include <fstream> using namespace std; //類模板中的成員函數(shù)在調用時才創(chuàng)建 (因為不知道是啥類型) //普通類中的成員函數(shù)一開始就創(chuàng)建 class Person1{ public:void showPerson1(){cout<<"showPerson1()"<<endl;} };class Person2{ public:void showPerson2(){cout<<"showPerson2()"<<endl;} }; template<class T> class Myclass{ public:T obj;//類模板中的成員函數(shù)void func1(){obj.showPerson1();}void func2(){obj.showPerson2();} }; void test06(){Myclass<Person1> m;m.func1();m.func1(); }int main() {test06();return 0; }

4.類模板對象做函數(shù)參數(shù)

#include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> using namespace std; //類模板對象做函數(shù)參數(shù) template<class T1, class T2> class Person{ public:Person(T1 name, T2 age){this->m_Name = name;this->m_Age = age;}void showPerson(){cout<< "姓名: " << this->m_Name <<" 年齡: "<< this->m_Age <<endl;}T1 m_Name;T2 m_Age; };//1.指定傳入類型 (最常用) void printPerson1(Person<string, int>&p){p.showPerson(); } //2.參數(shù)模板化 template<class T1, class T2> void printPerson2(Person<T1, T2>&p){p.showPerson();cout<<"T1類型: "<<typeid(T1).name()<<endl;cout<<"T2類型: "<<typeid(T2).name()<<endl; } //3.整個類模板化 template<class T> void printPerson3(T &p){p.showPerson();cout<<"T類型: "<<typeid(T).name()<<endl; } void test06(){Person<string, int>p("limin", 100);printPerson1(p);printPerson2(p);printPerson3(p); }int main() {test06();return 0; }

5.類模板與繼承

#include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> using namespace std;template<class T> class Base{ public:T m; }; //class Son1:public Base{ //錯誤的,必須要知道父類中的T類型,才能繼承給子類 class Son1:public Base<int>{}; template<class T1, class T2> class Son2:public Base<T2>{ //如果想靈活指定父類中的T類型,子類也需要變類模板 public:Son2(){cout<<" T1類型: "<<typeid(T1).name()<<endl;cout<<" T2類型: "<<typeid(T2).name()<<endl;}T1 obj; };void test06(){Son1 s1;Son2<int, char> s2; }int main() {test06();return 0; }

6.類模板成員函數(shù)類外實現(xiàn)

#include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> using namespace std;//類模板成員函數(shù)類外實現(xiàn) template<class T1, class T2> class Person{ public:Person(T1 name, T2 age);//類內(nèi)實現(xiàn)構造函數(shù) // Person(T1 name, T2 age){ // this->m_Name = name; // this->m_Age = age; // } // void showPerson(){ // cout<<" 姓名: "<<this->m_Name<< " 年齡: " <<this->m_Age<<endl; // }void showPerson();T1 m_Name;T2 m_Age; }; //構造函數(shù)類外實現(xiàn) template<class T1, class T2> Person<T1, T2>::Person(T1 name, T2 age){this->m_Name = name;this->m_Age = age; } //成員函數(shù)類外實現(xiàn) template<class T1, class T2> void Person<T1, T2>::showPerson(){cout<<" 姓名: "<<this->m_Name<< " 年齡: " <<this->m_Age<<endl; } void test06(){Person<string, int>p("limin", 100);p.showPerson(); }int main() {test06();return 0; }

7.類模板類分文件編寫

7.1.第一種方式:因為類模板成員函數(shù)一開始是不會創(chuàng)建的,所以包含.h頭文件不會創(chuàng)建類模板成員函數(shù),導致鏈接階段無法找到。而改為#include .cpp就可以看見.h成員函數(shù)和實現(xiàn)方式.

demo.cpp

#include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> //#include "Person.h" //錯誤不能調用 #include "Person.cpp" //改為.cpp文件就行 //#include "Person.hpp" //改為.hpp文件就行 里面包含函數(shù)聲明與實現(xiàn) using namespace std;void test06(){Person<string, int>p("limin", 100);p.showPerson(); }int main() {test06();return 0; }

Person.h

#pragma once //防止頭文件重復包含 #include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> using namespace std;//類模板成員函數(shù)類外實現(xiàn) template<class T1, class T2> class Person{ public:Person(T1 name, T2 age);void showPerson();T1 m_Name;T2 m_Age; };

Person.cpp

#include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> #include "Person.h" using namespace std; //構造函數(shù)類外實現(xiàn) template<class T1, class T2> Person<T1, T2>::Person(T1 name, T2 age){this->m_Name = name;this->m_Age = age; } //成員函數(shù)類外實現(xiàn) template<class T1, class T2> void Person<T1, T2>::showPerson(){cout<<" 姓名: "<<this->m_Name<< " 年齡: " <<this->m_Age<<endl; }

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1) project(Infantry) add_definitions(-std=c++11) set(CMAKE_BUILD_TYPE Debug) set(SRC_LIST demo.cpp Person.cpp Person.h) #set(SRC_LIST demo.cpp Person.hpp) add_executable(demo ${SRC_LIST})

7.2函數(shù)聲明和實現(xiàn)都在.hpp。

Person.hpp?

#pragma once //防止頭文件重復包含 #include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> using namespace std;//類模板成員函數(shù)類外實現(xiàn) template<class T1, class T2> class Person{ public:Person(T1 name, T2 age);void showPerson();T1 m_Name;T2 m_Age; }; //構造函數(shù)類外實現(xiàn) template<class T1, class T2> Person<T1, T2>::Person(T1 name, T2 age){this->m_Name = name;this->m_Age = age; } //成員函數(shù)類外實現(xiàn) template<class T1, class T2> void Person<T1, T2>::showPerson(){cout<<" 姓名: "<<this->m_Name<< " 年齡: " <<this->m_Age<<endl; }

demo.cpp?

#include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> //#include "Person.h" //錯誤不能調用 //#include "Person.cpp" //改為.cpp文件就行 #include "Person.hpp" //改為.hpp文件就行 里面包含函數(shù)聲明與實現(xiàn) using namespace std;void test06(){Person<string, int>p("limin", 100);p.showPerson(); }int main() {test06();return 0; }

CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1) project(Infantry) add_definitions(-std=c++11) set(CMAKE_BUILD_TYPE Debug) #set(SRC_LIST demo.cpp Person.cpp Person.h) set(SRC_LIST demo.cpp Person.hpp) add_executable(demo ${SRC_LIST})

8.類模板配合友元函數(shù)的類內(nèi)和類外實現(xiàn)

8.1.全局函數(shù)類內(nèi)實現(xiàn)

#include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> using namespace std;template<class T1, class T2> class Person{//全局函數(shù) 類內(nèi)實現(xiàn)friend void printPerson(Person<T1, T2> p){cout<<" 姓名: "<<p.m_Name<< " 年齡: " <<p.m_Age<<endl;} public:Person(T1 name, T2 age){this->m_Name = name;this->m_Age = age;} // void showPerson(){ // cout<<" 姓名: "<<this->m_Name<< " 年齡: " <<this->m_Age<<endl; // } private:T1 m_Name;T2 m_Age; }; void test06(){//全局函數(shù)類內(nèi)實現(xiàn)的測試Person<string, int>p("limin", 100);printPerson(p); }int main() {test06();return 0; }

8.2 全局函數(shù)類外實現(xiàn)

如果全局函數(shù)是類外實現(xiàn)的話 需要編譯器提前知道這個函數(shù)的存在

?

9.案例

MyClass.hpp

#pragma once //防止頭文件重復包含 #include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> using namespace std;//類模板成員函數(shù)類外實現(xiàn) template<class T> class MyArray{ public://有參構造MyArray(int capacity){cout<<"調用構造函數(shù)"<<endl;this->m_capacity = capacity;this->m_size = 0;this->pAddress = new T[this->m_capacity]; //開辟堆區(qū)空間}//拷貝構造函數(shù)MyArray(const MyArray<T>& arr){cout<<"調用拷貝構造函數(shù)"<<endl;this->m_capacity = arr.m_capacity;this->m_size = arr.m_size;this->pAddress = new T[arr.m_capacity];//深拷貝//將arr中的數(shù)據(jù)拷貝過來for(int i=0; i<this->m_size; i++){this->pAddress[i] = arr.pAddress[i];}}//尾插法void PushBack(const T& value){//先判斷是否等于大小if(this->m_capacity == this->m_size){return;}this->pAddress[this->m_size] = value; //尾插法this->m_size++; //更新數(shù)組大小}//尾刪法void PopBack(){//讓用戶訪問不了最后一個元素if(this->m_size == 0){return;}this->m_size--; //更新數(shù)組大小}//通過下標方式訪問數(shù)組中元素T& operator[](int index){return this->pAddress[index];}//返回數(shù)組容量int getCapacity(){return this->m_capacity;}//返回數(shù)組大小int getSize(){return this->m_size;}//operator= 也是防止淺拷貝MyArray& operator=(const MyArray<T>& arr){cout<<"調用operator= 函數(shù)"<<endl;//先判斷原來堆區(qū)是否與數(shù)據(jù),如果有先釋放if(this->pAddress != NULL){delete []this->pAddress;this->pAddress = NULL;this->m_capacity = 0;this->m_size = 0;}//深拷貝this->m_capacity = arr.m_capacity;this->m_size = arr.m_size;this->pAddress = new T[arr.m_capacity];//深拷貝//將arr中的數(shù)據(jù)拷貝過來for(int i=0; i<this->m_size; i++){this->pAddress[i] = arr.pAddress[i];}return *this;}virtual ~MyArray(){cout<<"調用析構函數(shù)"<<endl;if(this->pAddress != NULL){delete []this->pAddress;this->pAddress = NULL;}} private:int m_capacity;int m_size;T* pAddress; //指針指向堆區(qū)開辟的真實數(shù)組 };

demo.cpp

#include <iostream> #include <vector> #include <string> #include <typeinfo> #include <algorithm> #include <map> #include <fstream> #include "MyClass.hpp" using namespace std;void test06(){MyArray<int> arr1(20);MyArray<int> arr2(arr1);MyArray<int> arr3(10);arr3 = arr1;for(int i=0; i<5; i++){arr1.PushBack(i + 10);}cout<<" ==before arr1.getCapacity(): "<<arr1.getCapacity()<<endl;cout<<" ==before arr1.getSize(): "<<arr1.getSize()<<endl;for(int i=0; i<arr1.getSize(); i++){cout<<"before arr1[i]: " <<arr1[i]<<endl;}arr1.PopBack();arr1.PopBack();cout<<" ==after arr1.getCapacity(): "<<arr1.getCapacity()<<endl;cout<<" ==after arr1.getSize(): "<<arr1.getSize()<<endl;for(int i=0; i<arr1.getSize(); i++){cout<<"after arr1[i]: " <<arr1[i]<<endl;} } class Person{ public:Person(){};Person(string name, int age){this->m_Name = name;this->m_Age = age;};string m_Name;int m_Age; };void printPersonArray(MyArray<Person>& arr){for(int i=0; i<arr.getSize(); i++){cout<<" 姓名: "<<arr[i].m_Name<< " 年齡: "<<arr[i].m_Age<<endl;} } //測試自定義類型 void test07(){MyArray<Person> arr(10);Person p1("Damin",100);Person p2("Tony",70);Person p3("Tom",50);Person p4("Jarry",10);Person p5("Dalin",20);arr.PushBack(p1);arr.PushBack(p2);arr.PushBack(p3);arr.PushBack(p4);arr.PushBack(p5);printPersonArray(arr);cout<<" ==arr1.getCapacity(): "<<arr.getCapacity()<<endl;cout<<" ==arr1.getSize(): "<<arr.getSize()<<endl; }int main() { // test06();test07();return 0; }

測試int類型:

測試自定義類型Person:

參考:

https://www.bilibili.com/video/BV1et411b73Z?p=175&spm_id_from=pageDriver

總結

以上是生活随笔為你收集整理的C++模板的一些基础知识的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。