ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
## [$]一.实例化 ### 1.隐式实例化 模板被使用时,进行的模板的实例化。 对于类模板,若成员函数不使用,则不会进行实例化。 + **发生时机** 模板被使用时。 + **缺点** 相同的模板实例可能出现在多个对象文件中,造成了一定的额外开销。 #### 例1 ```c++ template <typename T> T add(const T &t1,const T &t2) { return t1+t2; } ``` 调用: ```c++ f(200,700);//隐式实例化 f<int>(300,600);//隐式实例化:尽管指定了模板实参,但模板仍在被使用时才进行实例化。 ``` ### [11+]2.显式实例化 1. 声明显式实例化:告诉编译器在其他地方有显式实例化的定义。 + 必须出现在使用之前,防止使用时的初始化。 ```c++ extern template class Array<int>;//类模板显式声明 extern template int add(const int &,const int &);//函数模板显式声明 ``` 2. 定义显式实例化:只能定义一次,此时编译器会为该模板生成代码。 + 当显式实例化类模板时,会实例化所有的成员函数。 ```c++ template class Array<int>;//类模板显式定义 template int add(const int &,const int &);//函数模板显式定义 ``` ## [$]二.模板特例化 ### 1.基本概念 1. **概念** 模板特例化是函数模板、类模板、成员模板的 **重定义** ,其中指定了部分或全部模板参数。 2. 模板特例化版本必须出现在原模板的声明之后。 3. 模板特例化的本质是实例化一个模板,而非重载它。 4. 当编译器匹配到特例化的版本时,编译器会直接使用特例化的版本,而不是重新实例化原来的模板。 ### 2.函数模板特例化 当我们特例化一个函数模板时,必须为原模板中的每个模板参数都提供模板实参。且提供的模板实参必须与模板匹配。 #### 例2 下面是一个函数的多个定义,以支持字符串、字符数组的比较。 ```c++ //通用模板 template <typename T> int compare(const T &t1, const T &t2) { cout << "调用第一个版本" << endl; if (t1 > t2) return 1; if (t1 == t2) return 0; if (t1 < t2) return -1; return 0; } //这是重载,不是特例化,用于字符数组的传入 template <unsigned N1, unsigned N2> int compare(const char (&p1)[N1], const char (&p2)[N2]) { cout << "调用第二个版本" << endl; return strcmp(p1, p2); } //特例化的模板,T=const char *,用于字符指针的传入 template <> int compare(const char *const &p1, const char *const &p2) { cout << "调用第三个版本" << endl; return strcmp(p1, p2); } ``` 调用: ```c++ const char *p1 = "apple"; const char *p2 = "zoo"; cout << compare(10, 9) << endl; cout << compare("apple", "zoo") << endl; cout << compare(p1, p2) << endl; ``` >[test] >调用第一个版本 >1 >调用第二个版本 >-1 >调用第三个版本 >-1 ### 3.类模板特例化 + 与函数模板不同,类模板的特例化不必为所有模板参数提供实参。 + 一个类模板的部分特例化本身是一个模板,使用它时还须提供其余的模板实参。 ```c++ //模板 template <typename T> class A { //code }; //特例化 class A<char *> { //code }; //部分特例化 template <typename T> class A<T&> { //code }; ``` ### 4.特例化成员 + 与函数模板类似,需要提供全部模板实参。 ```c++ template <typename T> class Array { private: static int size; //其他数据成员... public: void output() { //code } //其他函数... }; //特例化成员函数 template <> Array<int>::output() { //code } //特例化静态数据成员 template <> Array<int>::size = 20; ```