《C++ Primer》第16章 模板与泛型编程
16.3节 重载与模板 习题答案
练习16.48:编写你自己版本的debug_rep函数。
【出题思路】
理解模板重载。
【解答】
参考书中本节内容编写,与配套网站中的代码进行对照即可。尝试定义宏OVERCHAR(#define OVERCHAR)和SPECIALIZED(#define SPECIALIZED)来改变源码,重新编译运行程序,观察输出结果的差异(同时定义宏DEBUG,可以观察函数(模板)被调用的次序,更好地帮助你理解结果差异的原因)。例如,宏OVERCHAR只在SPECIALIZED未定义时起作用。程序总会定义接受string的非模板函数,若未定义OVERCHAR,则还会定义接受char *和const char*的非模板函数。因此,当未定义OVERCAR时,主程序中的
cout << debug_rep("hi") << endl;
会输出(打开了DEBUG):
const char * const string & "hi"
因为此时最佳匹配是接受const char *的非模板函数,它构造了一个string,继续调用debug_rep,因此又会匹配接受string的非模板函数。
std::string debug_rep(const char *p)
{
#ifdef DEBUG
std::cout << "const chaar *" << "\t";
#endif
return debug_rep(std::string(p));
}
而当定义OVERCHAR时,会输出:
T* const T& pointer: hi h
因为此时最佳匹配是接受T *的模板,它又调用debug_rep打印指针指向的值,又会匹配最通用的模板const T &。
template <typename T> std::string debug_rep(T *p)
{
#ifdef DEBUG
std::cout << "T*" << "\t";
#endif
std::ostringstream ret;
ret << "pointer:" << p;//打印指针自己的值
if(p)
ret << " " << debug_rep(*p);//打印p指向的值
else
ret << " null pointer";//p为空指针
return ret.str();//返回打印出的内容(保存在ret的字符串中)
}
而当打开SPECIALIZED后,输出为:
const string & "hi"
原因是,打开SPECIALIZED后,不再定义非模板函数,而只会定义模板的特例化版本,此时最佳匹配是接受const string &的特例化版本:
template<> std::string debug_rep(const std::string &s)
#endif
{
#ifdef DEBUG
std::cout << "const string &" << "\t";
#endif
return '"' + s " '"';
}
读者可自行分析主程序中其他debug_rep调用输出的异同。
练习16.49:解释下面每个调用会发生什么:
template <typename T> void f(T);
template <typename T> void f(const T*);
template <typename T> void g(T);
template <typename T> void g(T*);
int i = 42, *p = &i;
const int ci = 0, *p2 = &ci;
g(42); g(p); g(ci); g(p2);
f(42); f(p); f(ci); f(p2);
【出题思路】
理解模板重载。
【解答】
g(42)匹配模板3,T被推断为int。
g(p)匹配模板4,T被推断为int。
g(ci)匹配模板3,T被推断为int。
g(p2)匹配模板4,T被推断为const int。
f(42)匹配模板1,T被推断为int。
f(p)匹配模板1,T被推断为int*。
f(ci)匹配模板1,T被推断为int。
f(p2)匹配模板2,T被推断为int。
练习16.50:定义上一个练习中的函数,令它们打印一条身份信息。运行该练习中的代码。如果函数调用的行为与你的预期不符,确定你理解了原因。
【出题思路】
理解模板重载。
【解答】
#include <iostream>
#include <typeinfo>
using std::cout;
using std::endl;
template <typename T>
void f(T a)
{
cout << "f(T), T是" << typeid(T).name() << endl;
}
template <typename T>
void f(const T *a)
{
cout << "f(const T*), const T*是" << typeid(const T*).name() << endl;
}
template <typename T> void g(T a)
{
cout << "g(T*), T*是" << typeid(T*).name() << endl;
}
int main()
{
int i = 42, *p = &i;
const int ci = 0, *p2 = &ci;
g(42);
g(p);
g(ci);
g(p2);
f(42);
f(p);
f(ci);
f(p2);
return 0;
}
运行结果: