💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
## 一.函数模板 1. **概念** 建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟类型来代表。 2. **功能** 解决函数体完全一样,而函数类型和形参类型不一致的情况。 3. 一般形式 ```c++ template <class T1,...> ``` 其中, `class` 可以使用 `typename` 代替。 ```c++ #include <iostream> template <class T> //末尾没有分号,class也可以写成typename T max(T a,T b){ return a; } int main() { std::cout<<max(123,234);//调用时T编译器通过实参推导出T=int return 0; } ``` 4. 函数模板中,定义与声明的参数名可不相同。 ```c++ #include <iostream> template <class U> U max(U a,U b); int main() { std::cout<<max(123,234);//调用时T编译器通过实参推导出T=int return 0; } template <class T> //末尾没有分号,class也可以写成typename T max(T a,T b){ return a; } ``` 5. **实例化** ```c++ #include <iostream> template <class T> //末尾没有分号,class也可以写成typename T max(T a,T b){ return a > b ? a : b; } int main() { //实例化出 int max(int,int) std::cout<<max(123,234); return 0; } ``` >[test] >234 6. 模板实例化时,可以显式指定模板参数的类型。 ```c++ #include <iostream> template <class T> //末尾没有分号,class也可以写成typename T max(T a,T b){ return a > b ? a : b; } int main() { //实例化出 double max(double,double) std::cout<<max<double>(123,234.5); return 0; } ``` >[test] >234.5 ## 二.类模板 1. **概念** 类模板是用来生成类的蓝图的。与函数模板的不同之处是,编译器不能为类模板推断模板参数类型。 2. 声明类模板:在类声明前面添加模板声明。 3. 使用类模板:需要在类名后使用一对尖括号 `<>` 来表示模板参数的值。 ```c++ #include <iostream> using namespace std; //一维数组类 //声明一个类模板 template <typename T> class Array{ private: T* start_; int length_; public: /*构造函数*/ Array():start_(NULL),length_(0){}; Array(int length):start_(new T[length]),length_(length){} /*析构函数*/ ~Array() { if(this->start_ != NULL) delete[] this->start_; } /*拷贝构造函数*/ Array(const Array& arr) { this->start_ = new T[arr.length_]; this->length_ = arr.length_; for(int i = 0; i < arr.length_; i++) { this->start_[i] = arr.start_[i]; } } /*拷贝赋值函数*/ Array& operator=(Array& arr) { if(this->start_ != NULL) delete[] this->start_; this->start_ = new T[arr.length_]; this->length_ = arr.length_; for(int i = 0; i < arr.length_; i++) { this->start_[i] = arr.start_[i]; } return *this; } /*下标访问,溢出访问会抛出异常*/ T& operator[](int index) { if(index >= this->length_ || index < 0) throw -1; return this->start_[index]; } /*获取数组的大小*/ int length() { return this->length_; } }; int main() { //定义一个类模板的对象,必须使用尖括号声明模板参数的值 Array<int> a(2); a[0] = 2; a[1] = 3; cout<<a[1]; return 0; } ``` 4. 类模板外的成员函数 定义在类模板之外的成员函数,就必须以关键字template开始,后接类模板参数列表,并在类名后以 `<>` 传入模板参数。 ```c++ #include <string> using std::string; //声明一个栈类 template <typename T> class Stack { private: /*栈底,内部数组*/ T *base_; /*栈顶,指向下一个元素的指针*/ T *top_; /*最大长度*/ int max_length_; public: /*constructor*/ Stack(); Stack(unsigned int length); /*destructor*/ ~Stack(); /*remove*/ T pop(); /*add*/ Stack &push(T value); /*remove all*/ Stack &clear(); /*size*/ int length(); bool is_empty(); /*max size*/ int max_length(); /*access*/ T &top(); /*display*/ Stack<T> &traverse(); }; //定义成员函数 //必须以关键字template开始,后接类模板参数列表,并在类名后以 `<>` 传入模板参数。 //构造函数 template <typename T> Stack<T>::Stack() : base_(NULL), max_length_(0), top_(NULL) { } //构造函数 template <typename T> Stack<T>::Stack(unsigned int length) : base_(new T[length]), max_length_(length), top_(base_) { } //析构 template <typename T> Stack<T>::~Stack() { delete[] this->base_; } //弹出元素 template <typename T> T Stack<T>::pop() { if(this->is_empty()) throw string("Error:Stack Overflow."); this->top_--; /*指针前移*/ return *this->top_; /*这个就是被删除的元素*/ } //添加元素 template <typename T> Stack<T> &Stack<T>::push(T value) { if (this->length() < this->max_length()) { *this->top_ = value; this->top_++; } else { throw string("Error:Stack is full."); } return *this; } //清空元素 template <typename T> Stack<T> &Stack<T>::clear() { this->end = this->base_; return *this; } //栈的长度 template <typename T> int Stack<T>::length() { return this->top_ - this->base_; } //是否为空 template <typename T> bool Stack<T>::is_empty() { return this->length() == 0; } //最大长度 template <typename T> int Stack<T>::max_length() { return this->max_length_; } ``` ## [$]三.类模板与友元 ```c++ //1.非类模板将一个类模板的任何实例声明为友元。 template <typename T> friend class Goods; class People{ template <typename T> friend class Goods;//支持任意类型的私人财产 }; //2.非类模板将一个类模板的特定实例声明为友元。 template <typename T> friend class Goods; class Food; class People{ friend class Goods<Food>;//支持吃的私人财产 }; //3.类模板将一个类模板的任何实例声明为友元。 class Food; template <typename T> friend class Goods; template <typename T> class Student{ friend class Goods<Food>;//支持吃的私人财产 }; //4.类模板将一个类模板的特定类型实例声明为友元。 class Food; template <typename T> friend class Goods; //小学生,中学生,大学生 template <typename T> class Student{ friend class Goods<Food>;//支持吃的私人财产 }; //5.类模板将一个类模板的相同类型实例声明为友元。 //小学生,中学生,大学生 template <typename T> class Student{ friend class Tutor<T>; }; //6.类模板将一个类模板的任意类型实例声明为友元。 template <typename T> class Student{ template <typename T1> friend class Tutor; }; //[11+]7.将模板类型参数声明为友元 template <typename T> class Student{ friend T; }; ``` ## [$]四.模板类型别名 + 用 `typedef` 或 `using` 声明模板类型别名 ```c++ typedef Student<Primary> PrimaryStudent; //[11+]下面代码只支持C++11及以上标准的编译器。 using PrimaryStudent = Student<Primary>; ```