by Yazy -- 2005, 04.23
如果我们要实现一个支持多种输入类型的函数,在C++里我们可以
使用“重载”:
void test(int n)
{
cout<<"test(int): "<<n<<endl;
}
void test(float n)
{
cout<<"test(float): "<<n<<endl;
}
void test(short n)
{
cout<<"test(short): "<<n<<endl;
}
重载的思想是为每一种特定的类型去实现一个函数实体。这种方
式可能会给函数的使用者带来极大的便利,这种便利体现在用户
只须记住一个函数,而不必去为不同的类型选用其特定的函数调
用,因为“重载”的实现方式将这种“选择”定性地交给了编绎
器做了。所以“重载”是有助于用户使用函数来开发程序的,有
助于代码复用效率。
而重载的缺点是:它加重了函数开发者的开发负担。按“以用户
为中心”的思想,重载牺牲开发者更多的时间与精力,换来更多
的用户利益。函数作者需要负出更多的努力,体现于作者要写多
个版本的同一个函数;作者要保证函数的每一个版本都具有正确
或者通常是一致的语义。可能开发者要为这个保证负出更多,有
时候复杂的问题使得这种保证变得不那么有意义。
C++的template可以将要用到的类型泛化。比如在一个函数可能用
到一种未确知的类型 T,它可能是 int、float、short 或是某个
自定义类型。Template 可以让开发者使用这种“未知”,将这种
“未知”状态保留至函数被使用并且代码被编绎。 这种“未知”
的类型便是“泛化的类型”,使用这种编程范式的程序被称作“
泛型程序”。
上面的 test 使用泛型编程方式来作便可能是:
template<class T>
void test(T n)
{
cout<<"template<class T> void test(T): "<<n<<endl;
}
相比于“重载”,泛型的函数可以应用于更多的类型,甚至常常很难
确定它可以被用于多少种类型,而重载函数通常被使用于极有限数量
的类型。
泛型函数通常只要求输入类型符合某些特性,而不理会其具体是什么
类型。例如,某个泛型函数可能要求输入类型必须可以参加算术运算、
逻辑运算或是某种接口(例如 STL 里的 iterator)。
在C++里泛型还可以“泛”常数,即将“未知”状态赋予一种常数:
template<class T, int SIZE>
void test(T n)
{
int nums[SIZE];
//...
cout<<"Size: "<<SIZE<<endl
<<"Para: "<<n<<endl;
}
泛型还包括:默认模板参数、特化等。有待学习……