【C++】浅谈对模板的认识
2017-10-23 22:42
441 查看
如果要写出适合于所有类型的函数,你会怎么写?
首先想到的应该就是函数重载了吧,函数重载使非常容易想到的,但是却存在许多缺点。比如:只要有新的类型出现,就需要添加新的函数;如果函数只有返回值不同,函数重载就不能解决了,除此之外,还有函数体都相同,仅有类型不同,代码显得冗杂;不方便维护等问题。
其次,我们还可以想到借助公共基类,将通用的代码放到基类中,但是这样仍然难以维护代码,而且会失去类型检查这一优点。
此外,还有宏函数业可以完成,但同样,不会进行类型检查,安全性不够。
在C++中,我们有一个很好的办法可以达到目的,那就是模板了。编写与类型无关的逻辑代码,我们称之为泛型编程,而模板就是泛型编程的基础。
模板关键字:template,可以分为函数模板和类模板。
一. 函数模板
1.函数模板的格式:
template <typename 模板形参名字>
返回值类型 函数名(参数列表)
{}
例如:
(2).inline关键字也可以被模板使用,放置于模板参数列表之后,函数返回值之前。
例如:
(1).模板本身不是一个类或者函数,编译器用模板产生指定类型的函数或类,这一过程称之为模板实例化。
(2)模板在编译时可以理解为编译了两次,第一次是实例化之前,检查代码是否存在语法错误;第二次是在实例化期间,检查模板代码,查看是否所有的调用都有效。
注意:(1)隐式实例化中,模板中不会出现类型转换,只会产生新的实例。例如:
(3)编译器将会执行两种转换:一种是接受const的函数,可以用非const对象的引用或指针调用;另一种是数组或函数到指针的转换。
3. 函数模板的参数
(1)类型形参
a. 模板形参名字只能在模板形参之后到模板的定义或声明之间使用,遵循名字屏蔽,例如:
b. 模板形参的名字在同一个模板形参中只能出现一次
非模板类型形参是模板内部定义的常量,在需要常量表达式的时候,可以使用非模板类型参数
所有重载版本的生命都应放于该函数被调用的位置之前。
5. 模板函数的特化
对于上述例子,比较两个参数中较大的一个,并不能适用于字符串,因此,我们需要对于字符串这种类型进行特化。
(1)关键字template<>
(2)函数名后一对尖括号,尖括号内指定特化定义的模板形参
(3)函数形参表中注意const的位置
例如:
模板类同模板函数类似,关键字为template
template<typename 形参1, typename 形参2>
class 类名
{};
我们写过的模板顺序表,链表就是应用模板类的
模板类的特化可以分为:全特化,偏特化
注意:偏特化并不仅仅是特化部分参数,而应该是针对模板参数更进一步的条件限制出来的一个特化版本。
三. 模板的分离编译
分离编译就是将函数的实现与调用不在同一个文件中,当模板分离编译时,在编译阶段没有问题,但是程序最终却会出现问题。
因为在分离式的编译环境下,编译器分别编译不同的cpp文件时,遇到未解决的符号时,在最终链接时会得到解决。而遇到模板时,模板仅在需要的时候才会实例化,因此,当实现该模板的cpp文件中没有用到模板实例时,编译器并不会实例化,工程中的obj文件中没有模板实例的二进制代码,连接器没办法处理为解决的符号,因此会报出错误。
首先想到的应该就是函数重载了吧,函数重载使非常容易想到的,但是却存在许多缺点。比如:只要有新的类型出现,就需要添加新的函数;如果函数只有返回值不同,函数重载就不能解决了,除此之外,还有函数体都相同,仅有类型不同,代码显得冗杂;不方便维护等问题。
其次,我们还可以想到借助公共基类,将通用的代码放到基类中,但是这样仍然难以维护代码,而且会失去类型检查这一优点。
此外,还有宏函数业可以完成,但同样,不会进行类型检查,安全性不够。
在C++中,我们有一个很好的办法可以达到目的,那就是模板了。编写与类型无关的逻辑代码,我们称之为泛型编程,而模板就是泛型编程的基础。
模板关键字:template,可以分为函数模板和类模板。
一. 函数模板
1.函数模板的格式:
template <typename 模板形参名字>
返回值类型 函数名(参数列表)
{}
例如:
template <typename T> T Max(const T& a, const T& b) { return a > b ? a : b; }注意:(1).typename是定义模板的关键字,可以用class,但是不可以使用struct代替class
(2).inline关键字也可以被模板使用,放置于模板参数列表之后,函数返回值之前。
例如:
template <typename T> inline T Max(const T& a, const T& b) { return a > b ? a : b; }2.函数模板编译
(1).模板本身不是一个类或者函数,编译器用模板产生指定类型的函数或类,这一过程称之为模板实例化。
(2)模板在编译时可以理解为编译了两次,第一次是实例化之前,检查代码是否存在语法错误;第二次是在实例化期间,检查模板代码,查看是否所有的调用都有效。
注意:(1)隐式实例化中,模板中不会出现类型转换,只会产生新的实例。例如:
cout << Max(1, '2') << endl; //编译器将会报错当出现自己写的代码时,将会调用自己写的代码,模板将不会实例化,例如:
int Max(const int& a, const int& b) { return a > b ? a : b; } cout << Max(1, 2) << endl;//将会调用自己写的代码,不调用模板实例化的函数 cout << Max(1, '2') << endl;//将不会报错,调用自己写的代码,发生类型转换(2)显示实例化中,将只会调用模板实例化生成的函数。Max<>(1,2); Max<int>(1,2);
(3)编译器将会执行两种转换:一种是接受const的函数,可以用非const对象的引用或指针调用;另一种是数组或函数到指针的转换。
3. 函数模板的参数
(1)类型形参
a. 模板形参名字只能在模板形参之后到模板的定义或声明之间使用,遵循名字屏蔽,例如:
b. 模板形参的名字在同一个模板形参中只能出现一次
template <typename T, class T>//重定义 模板 参数“T”c. 函数模板内部不能指定缺省模板实参,类模板中可以使用默认参数
template <typename T=int >//在VS2013中经过编译器优化,可以编译通过 void Test(const T& t) { cout << typeid(t).name() << endl; }(2)非模板类型参数
非模板类型形参是模板内部定义的常量,在需要常量表达式的时候,可以使用非模板类型参数
template <typename T,int N> void Funtest(T(&_arr) )//数组的引用 { for (int i = 0; i < N; i++) _arr[i] = i; }4. 模板函数重载
所有重载版本的生命都应放于该函数被调用的位置之前。
5. 模板函数的特化
对于上述例子,比较两个参数中较大的一个,并不能适用于字符串,因此,我们需要对于字符串这种类型进行特化。
(1)关键字template<>
(2)函数名后一对尖括号,尖括号内指定特化定义的模板形参
(3)函数形参表中注意const的位置
例如:
template <typename T> T Max(const T& a, const T& b) { return a > b ? a : b; }二. 模板类
template<>//const修饰的是a,a的指向不能被改变,而const char* & b中,const修饰的是*a,a指向的空间的值不能被改
char* Max<char*>(char* const& a, char* const& b)
{
if (strcmp(a, b)==1)
return a;
return b;
}
模板类同模板函数类似,关键字为template
template<typename 形参1, typename 形参2>
class 类名
{};
我们写过的模板顺序表,链表就是应用模板类的
模板类的特化可以分为:全特化,偏特化
注意:偏特化并不仅仅是特化部分参数,而应该是针对模板参数更进一步的条件限制出来的一个特化版本。
三. 模板的分离编译
分离编译就是将函数的实现与调用不在同一个文件中,当模板分离编译时,在编译阶段没有问题,但是程序最终却会出现问题。
因为在分离式的编译环境下,编译器分别编译不同的cpp文件时,遇到未解决的符号时,在最终链接时会得到解决。而遇到模板时,模板仅在需要的时候才会实例化,因此,当实现该模板的cpp文件中没有用到模板实例时,编译器并不会实例化,工程中的obj文件中没有模板实例的二进制代码,连接器没办法处理为解决的符号,因此会报出错误。
相关文章推荐
- C++模板的认识(一)函数模板
- 对C++中为模板定义特殊的实现的认识
- C++模板浅谈
- 对C++ 的模板初步认识
- C++浅谈模板
- 浅谈C++模板
- C++ 函数模板,类模板初步认识
- 写模板string类, 认识STL的模块分离策略----小话c++(7)
- 对C++模板的新认识
- 浅谈C++模板机制
- 对C++中函数模板的认识
- 浅谈Java和C#泛型及C++模板
- 浅谈C++模板,template method,strategy异同
- 关于c++中模板的浅谈
- 对C++中模板的实例化的机制的认识
- c++模板引擎
- C++:模板
- c++对内存的浅谈以及内存泄漏问题的探讨之一
- C++模板深入理解
- 设计模式C++实现(5)——原型模式、模板方法模式