赞
踩
模板是c++的一种特性,允许函数或者类(对象)通过泛型(generic types)的形式表现或者运行
模板可以使得函数或类在对应不同的类型(types)的时候正常工作,而无需为每一种类型分别写一份代码。
1:函数模板(function tempalte):使用泛型参数的函数(function with generic parameters)
2:类模板(class template):使用泛型参数的类(class with generic parameters)
模板的声明(declaration)其实并未给出一个函数或者类的完全定义(definition),只是提供了一个函数或者类的语法框架(syntactical skeleton)
实例化是指从模板构建出一个真正的函数或者类的过程。用具体类型代替模板参数的过程叫做实例化;从而产生一个模板实例。
如果实例化一种类型,而该类型并不支持函数所使用的操作,那么就会导致一个编译错误。
1:显示实例化-在代码中明确指定要针对哪种类型进行实例化
2:隐式实例化-在首次使用时根据具体情况使用一种合适的类型进行实例化
函数模板编译(两次):
1:没有实例化之前,检查代码本身是否有语法错误。
2: 实例化期间,检查对模板代码的调用是否合法。
函数模板是参数化的一族函数(a famliy of functions)
通过函数模板,可以实例化一系类函数,这些函数都给予同一套模板框架,但是作用在不通类型的参数上
示例 :(针对不同的数据类型 比较两个数据的大小)
- #include <iostream>
- template <typename T> //模板参数由关键字typename(也可以使用class) 定义 定义一个函数模板 返回两个数中数值大的那一个
- inline T max(const T &a,const T &b)//函数有两个参数 ,类型为定义
- {
- return a>b?a:b;
- }
- int main()
- {
- int a =1;
- int b =2;
- auto ret = max<int>(a,b);
- std::cout<<"int ret = "<<ret<<std::endl;
- double da=1;
- double db =2;
- auto ret1 = max(da,db);
- std::cout<<"double ret1 = "<<ret1<<std::endl;
- return 0;
- }
模板参数是由传递给模板函数的实参决定的
不允许自动类型转换:每个T必须严格匹配
- #include <iostream>
- template <typename T> //模板参数由关键字typename(也可以使用class) 定义 定义一个函数模板 返回两个数中数值大的那一个
- inline T max(const T &a,const T &b)//函数有两个参数 ,类型为定义
- {
- return a>b?a:b;
- }
- int main()
- {
- int a =1;
- double b =2.0;
- //auto ret = max(a,b); //error 模板只有一种参数 但是这里传入了两种类型的参数
- //解决办法
- //用static_cast 强制转换参数类型使得 参数匹配
- auto ret1 = max(static_cast<double>(a),b);
-
- //显示指定T的类型
- auto ret2 = max<double>(a,b);
-
- return 0;
- }
参数不匹配报错
函数模板重载
- #include <iostream>
- template <typename T> //模板参数由关键字typename(也可以使用class) 定义 定义一个函数模板 返回两个数中数值大的那一个
- inline T max(const T &a,const T &b)//函数有两个参数 ,类型为定义
- {
- return a>b?a:b;
- }
-
- #include <iostream>
- template <typename T>
-
- inline T max(const T &a,const T &b,const T &c)
- {
- T temp;
- if(a<b)
- {
- temp = b;
- }
- else
- {
- temp = a;
- }
- return temp >c?temp :c;
-
- }
-
- inline int max(const int &a,const int &b)
- {
- return a>b?a:b;
- }
-
- template <typename T,typename T1=double>
- inline T max(const T &a,const T1 &b)
- {
- std::cout<<"template <typename T,typename T1=double> "<<std::endl;
- return a>b?a:b;
- }
-
- int main()
- {
- max(1,2,3); // max(const T &a,const T &b,const T &c) max<int>
- max(1.0,2.3); //max(const T &a,const T &b) max<double>
- max('a','b'); //max(const T &a,const T &b) max<char>
- max(1,2); //inline int max(const int &a,const int &b)
- max<>(1,2); //max(const T &a,const T &b) max<int>
- max<int>(1,2); //max(const T &a,const T &b) max<int>
- max('a',2); //inline int max(const int &a,const int &b)
- return 0;
- }
与函数模板类似,类也可以通过参数泛化,从而可以构建出一族不同的类实例(对象)
类模板实参可以是某一类型或常量(仅限int或enum)
示例
- #include<iostream>
- #include<vector>
- /*********************************************************
- *T可以是任意类型
- *模板实参也可以是一个int或enum类型的常量 size_t实际是int类型
- *n是编译时定义的常量
- *n可以有默认值
- *size_t类型的成员变量可以用n初始化
- ***********************************************************/
- const std::size_t DefaultStackSize = 1024;
- template <typename T,std::size_t n = DefaultStackSize>
- class Stack
- {
- public:
- void Push(const T &element);
- int Pop(T &element);
- //int Top(T &element) const;
- private:
- std::vector<T> m_Members;
- std::size_t m_mMaxSize = n;
- };
-
- template <typename T,std::size_t nMaxSize>
- void Stack<T,nMaxSize>::Push(const T &element)
- {
- if(m_mMaxSize <= m_Members.size())
- {
- return;
- }
- m_Members.push_back(element);
- }
-
- template <typename T,std::size_t nMaxSize>
- int Stack<T,nMaxSize>::Pop(T& element)
- {
- if(m_Members.empty())
- {
- return -1;
- }
- element = m_Members.back();
- m_Members.pop_back();
- return 0;
- }
-
-
- int main()
- {
- Stack<int> stack;
- Stack<int,100> stack1;
- for(int i =0;i<100;i++)
- {
- stack.Push(i);
- }
- int i;
- stack.Pop(i);
- std::cout<<i<<std::endl;
- stack.Pop(i);
- std::cout<<i<<std::endl;
- return 0;
- }
允许对一个类模板的某些模板参数类型做特化
对于某种特殊的类型,可能可以做些特别的优化或提供不同的实现
避免在实例化的时候引起一些可能不好的行为
特化一个类模板的时候也意味着需要特化其所有参数化的成员函数
示例:
- #include<iostream>
- #include<vector>
- /*********************************************************
- *T可以是任意类型
- *模板实参也可以是一个int或enum类型的常量 size_t实际是int类型
- *n是编译时定义的常量
- *n可以有默认值
- *size_t类型的成员变量可以用n初始化
- ***********************************************************/
- const std::size_t DefaultStackSize = 1024;
- template <typename T,std::size_t n = DefaultStackSize>
- class Stack
- {
- public:
- void Push(const T &element);
- int Pop(T &element);
- //int Top(T &element) const;
- private:
- std::vector<T> m_Members;
- std::size_t m_mMaxSize = n;
- };
-
- template <typename T,std::size_t nMaxSize>
- void Stack<T,nMaxSize>::Push(const T &element)
- {
- if(m_mMaxSize <= m_Members.size())
- {
- return;
- }
- m_Members.push_back(element);
- }
-
- template <typename T,std::size_t nMaxSize>
- int Stack<T,nMaxSize>::Pop(T& element)
- {
- if(m_Members.empty())
- {
- return -1;
- }
- element = m_Members.back();
- m_Members.pop_back();
- return 0;
- }
- template <>
- class Stack<std::string>
- {
- public:
- void Push(const T &element);
- int Pop(T &element);
- //int Top(T &element) const;
- private:
- std::list<string> m_Members;
- std::size_t m_mMaxSize;
- };
-
- int main()
- {
- Stack<int> stack;
- Stack<int,100> stack1;
- for(int i =0;i<100;i++)
- {
- stack.Push(i);
- }
- int i;
- stack.Pop(i);
- std::cout<<i<<std::endl;
- stack.Pop(i);
- std::cout<<i<<std::endl;
- return 0;
- }
类模板也可以偏特化
- template <typename T1,typename T2>
- class MyClass
- {
- };
-
- //偏特化
- template <typename T>
- class MyClass<T,T>
- {};
-
- template <typename T1,typename T2>
- class MyClass<T1*,T2*>
- {};
-
-
- template <typename T>
- class MyClass<T,int>
- {};
-
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。