让我们来稍微修改一下程序35,传递字符串值(而不是int或float)作为参数,并看看结果吧。
程序42.
#include <iostream> using namespace std;
template <typename T> T Maximum(T a, T b) { return a > b a : b; }
int main() { cout << Maximum("Pakistan", "Karachi") << endl;
return 0; } |
程序的输出为Karachi。(译注:在我的Visual Studio.net 2003下的输出却为Pakistan,这不同的原因是编译器组织字符串地址的方式不同决定的,但是Maximum函数的结果是应该返回内存高位的那个地址的,这和作者说的道理是一致的。)为什么呢?因为这里char*作为模板参数传递, Karachi在内存中存储的位置更高,而>运算符仅仅比较这两个地址值而不是字符串本身。
那么,如果我们希望基于字符串的长度来比较而不是地址的话,应该怎么做呢?
解决的办法是对char*数据类型进行模板的特化。下面是一个模板特化的例子。
程序43.
#include <iostream> using namespace std;
template <typename T> T Maximum(T a, T b) { return a > b a : b; }
template <> char* Maximum(char* a, char* b) { return strlen(a) > strlen(b) a : b; }
int main() { cout << Maximum("Pakistan", "Karachi") << endl;
return 0; } |
至于类模板,也可以用相同的办法进行特化。
程序44.
#include <iostream> using namespace std;
template <typename T> class TestClass { public: void F(T pT) { cout << "T version" << ''\t''; cout << pT << endl; } };
template <> class TestClass<int> { public: void F(int pT) { cout << "int version" << ''\t''; cout << pT << endl; } };
int main() { TestClass<char> obj1; TestClass<int> obj2;
obj1.F(''A''); obj2.F(10);
return 0; } |
程序的输出为:
T version A int version 10 |
ATL中就有若干类是类似这样的特化版本,例如在ATLBASE.H中定义的CComQIPtr。
模板也可以在不同的设计模式中使用,例如策略设计模式可以使用模板实现。
程序45.
#include <iostream> using namespace std;
class Round1 { public: void Play() { cout << "Round1::Play" << endl; } };
class Round2 { public: void Play() { cout << "Round2::Play" << endl; } };
template <typename T> class Strategy { private: T objT; public: void Play() { objT.Play(); } };
int main() { Strategy<Round1> obj1; Strategy<Round2> obj2;
obj1.Play(); obj2.Play();
return 0; } |
在这里,Round1和Round2为一个游戏中不同的关卡类,并且Strategy类依靠传递的模板参数来决定该做些什么。
程序的输出为:
ATL就是使用Strategy设计模式来实现线程的。
|