C++Primer_Chap16_模板和泛型编程_List03_重载和模板_笔记

  函数模板可以被另一个模板或普通非模板函数重载。与往常一样,名字相同的函数必须具有不同数量和类型的参数。涉及函数模板,函数匹配规则会在以下几方面受到影响:

  • 对于一个调用,其候选函数包括所有模板实参推断成功的函数模板实例
  • 候选的函数模板总是可行的,因为模板实参推断会排除任何不可行的模板
  • 可行函数(模板和非模板)按类型转换来排序。当然,可以用于函数模板调用的类型转换是非常有限的
  • 如果一个函数提供比任何其他函数都更好的匹配,则选择此函数。但如果有多个函数提供相同好的匹配,则:

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

--------如果同样好的函数中没有非模板函数,而且有多个函数模板,且其中一个模板比其他更具特例化,则选择此模板

--------否则,调用有歧义。

编写重载模板

//通用版本
template <typename T> string debug_rep(const T &t)
{
    ostringstream ret;
    ret << t;
    return ret.str();
}

//指针版本
//不能用于char *
template <typename T> string debug_rep(T *p)
{
    ostringstream ret;
    //IO库定义了一个char*值的<<版本
    ret << "pointer: " << p;
    if(p)
        ret << " " << debug_rep(*p);
    else
        ret << "null pointer";
    return ret.str();
}

string s("hi");
cout << debug_rep(&s) << endl;

  对于使用一个指针调用debug_rep,两个函数都生成可行的实例:

  • debug_rep(const string *&),由第一个版本的debug_rep实例化而来,T被绑定到string*
  • debug_rep(string*),由第二个版本的debug_rep实例化而来,T被绑定到string

  第二个版本的debug_rep的实例是此调用的精准匹配。第一个版本的实例需要进行普通指针到const指针的转换。正常函数匹配规则告诉我们应该选择第二个模板。

多个可行模板

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

  此例中的两个模板都是可行的,且是精确匹配:

  • debug_rep(const string *&),由第一个版本的debug_rep实例化而来,T被绑定到string*
  • debug_rep( const string*),由第二个版本的debug_rep实例化而来,T被绑定到string

  根据重载函数模板的特殊规则,此调用被解析成debug_rep(T*),即更特例化的版本。设计这条规则的原因是:没有它,将无法对一个const的指针调用指针版本的debug_rep。问题在于模板debug_rep( const T&)本质上可以用于任何类型,包括指针类型。

重载模板和类型转换

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

cout << debug_rqp("hi world!" ) << endl;

  三个debug_rep版本都可行:

  • debug_rep(const T&),T被绑定到char[10]
  • debug_rep( T*),T被绑定到const char
  • debug_rep( const string&),要求从const char*到string的类型转换

  对给定实参来说,两个模板都提供精确匹配——第二个模板需要进行一次(许可的)数组到指针的转换,而对于函数匹配来说,这种转换被认为是精确匹配的。非模板版本时可行的,但需要进行一次用户定义的雷璐转换,因此它没有精确匹配那么好,所以两个模板称为可调用的函数。T*更特例化,编译器会选择它。

缺少声明可能导致程序行为异常

猜你喜欢

转载自blog.csdn.net/accumulating_mocai/article/details/83856811