您的位置:首页 > 编程语言 > C语言/C++

C++primer阅读笔记-模板与泛型编程(重载与模板)

2015-09-07 11:10 453 查看
函数模板可以被另一个模板或者一个非模板函数重载,名字相同的函数必须具有不同数量或类型的参数。

设计到函数模板,函数匹配规则满足:

对于一个调用,其候选函数包括所有模板实参推断成功的函数模板实例

候选函数总是可行的,因为模板实参推断会排出任何不可行的模板

可行函数按照类型转换来排序

如果恰有一个函数提供比其他函数都更好的匹配,则选择此函数,如果有多个函数提供同样好的匹配,则:

如果同样好的函数中只有一个非模板函数,则选择此函数

如果没有非模板函数,有多个函数模板,则选择其中一个比其他模板更特例化的模板

否则此调用有歧义

编写重载模板

下面函数可以生成一个对象对应的string表示,该对象是任何具备输出运算符的类型

//打印任何我们不能处理的类型
template<tyename T>string debug_rep(const T &t)
{
ostringstream ret;
ret << t;
return ret.str();//返回ret绑定的string副本
}


下面是打印指针的debug_rep版本

//打印任何我们不能处理的类型
template<tyename T>string debug_rep(const T *t)
{
ostringstream ret;
ret << t;
if(t)
ret << "pointer:" << p;
else
ret << "null pointer";
return ret.str();//返回ret绑定的string副本
}


string s("hello");
debug_rep(s);//调用第一个版本的debug_rep


只有第一个版本的debug_rep是可行的,第二版本要求一个指针参数

debug_rep(&s);//调用第二版本的debug_rep


第一版本能生成实例,其T的类型是string *,需要进行普通指针到const指针的转换

第二版本T类型为string,此为更精确匹配

多个可行版本

考虑一下代码:

const string *sp = &s;
cout << debug_rep(sp) <<endl;


两个版本都是可行的,都是精确匹配

第一个版本实例为:
debug_rep<string&>(const string *&)
,T被绑定为string*

第二个版本实例为:
debug_rep<const string>(const string *)
,T被绑定为const string

由于第二版本比第一版本更加特例化,固解析为第二版本。

非模板和模板重载

string debug_rep(const string &s)
{
return'"'+s+'"';
}


考虑下边代码

string s("hello");
debug_rep(s);//调用第三个非模块版本的debug_rep


第一和第三个版本都能提供同样好的匹配

第一版本实例化为
debug_rep<string>(const string &)
,T被绑定到string

存在同样好的模板和非模板函数时,编译器会选择非模板函数,当存在多个同样好的非模板函数时,编译器会选择最特例化的版本,一个非模板函数比模板函数更加特例化

重载与类型转换

考虑下边代码

cout << debug_rep("hello");//调用第二版本


上述三个版本都可行

debug_rep(const T&),T为char[6]

debug_rep(T*),T为const char*

debug_rep(const string&),要求从const char*到string的类型转换

对给定的实参来说,第二个版本需要一次数组到指针的转换,这是精确匹配

非模板版本需要一次用户定义的类ixngzhuanhuan,因此没有精确匹配那么好

缺少生命可能导致程序行为异常

使用一个忘记声明的函数,代码将会编译失败

对于重载函数模板的函数,如果编译器可以从模板实例化出与调用匹配的版本,则缺少的声明就不重要了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息