1)如何使用函数模板和类模板?
函数模版通过在函数声明前加上模版参数列表来定义,调用时编译器根据实参类型自动推导模版参
数。类模板在定义类时使用模版参数列表,创建对象时指定具体的模版参数类型。
1.函数模版的使用
定义函数模版
template <typename T> // 或者template <class T>,这里T是模板参数
T myFunction(T a, T b) {
return a + b;
}
这里template 是模板参数列表的开头部分,typename(也可以用class,它们在这种情况下是等价
的)关键字表示T是一个模板参数,它可以代表任何类型。myFunction函数是一个函数模板,它接
受两个相同类型T的参数a和b,并返回它们的和。
调用函数模板
隐式推导类型调用:编译器可以根据传入的实参类型自动推导模板参数T的类型。例如:
int main() {
int num1 = 5;
int num2 = 3;
int result1 = myFunction(num1, num2); // 编译器自动推导T为int
return 0;
}
在这个例子中,当我们调用myFunction(num1, num2)时,编译器看到传入的实参num1和num2是
int类型,所以自动将模板参数T推导为int,并生成一个对应的函数版本,就好像我们定义了一个普
通的int myFunction(int a, int b)函数一样。
显式指定类型调用:也可以显式地指定模板参数的类型,这种方式在某些复杂的情况下或者需要强
制指定类型时很有用。例如:
int main() {
double num3 = 2.5;
double num4 = 3.5;
int result2 = myFunction<double>(num3, num4); // 显式指定T为double,但返回值强制转换为int
return 0;
}
这里myFunction(num3, num4)显式地告诉编译器将模板参数T指定为double。不过要注意,在这个
例子中,函数的返回值是double类型相加的结果,但是我们将它赋值给了一个int类型的变量
result2,会发生隐式类型转换。
2.类模版的使用
定义类模版
template <typename T>
class MyClass {
public:
MyClass(T data) : m_data(data) {}
T getData() const { return m_data; }
private:
T m_data;
};
这里template 定义了类模板,MyClass是一个类模板,它有一个成员变量m_data和一个成员函数
getData。成员变量和成员函数都依赖于模板参数T,这意味着它们的类型会根据T的具体类型而变
化。
使用类模板创建对象
指定模板参数类型创建对象:在创建类模板对象时,需要指定模板参数的类型。例如:
int main() {
MyClass<int> myObj1(5); // 指定T为int
int data1 = myObj1.getData();
MyClass<double> myObj2(3.14); // 指定T为double
double data2 = myObj2.getData();
return 0;
}
在这个例子中,MyClass myObj1(5)创建了一个MyClass类模板的对象myObj1,并显式地指定模板
参数T为int。类似地,MyClass myObj2(3.14)创建了一个T为double的对象myObj2。这样,
myObj1中的成员变量m_data是int类型,myObj2中的m_data是double类型,它们的getData函数返
回值类型也相应地不同。
2)模板的优点是什么?
提高代码的可重复性,减少代码重复,类型安全,增强程序的灵活性和扩展性
1.代码复用性高,减少了代码重复
模板允许编写通用的代码,可以处理多种不同类型的数据,而不需要为每种数据类型都编写重
复的代码。例如,前面定义的add函数模板可以用于整数、浮点数、甚至自定义的类(只要该
类定义了加法运算符)。这大大减少了代码量,提高了代码的复用性。对于类模板也是如此,
像Array类模板可以用于创建不同类型和大小的数组,避免了为每种类型和大小的数组都编写
一个独立的类。
2.类型安全
模板在编译时会进行类型检查。编译器会根据实际使用的类型生成相应的代码,并对这些代码
进行类型检查。这意味着可以在编译阶段发现很多类型不匹配的错误,而不是在运行时出现难
以调试的问题。例如,在add函数模板中,如果试图将一个int和一个string相加(假设没有为
这种操作定义合适的加法规则),编译器会报错,因为这种操作不符合函数模板对于参数类型
的要求。
3.灵活性和可扩展性
可以很容易地修改或扩展模板。如果需要在add函数模板中添加一些额外的功能,如对相加结
果进行某种特殊的处理,只需要在模板定义中修改函数体即可。对于类模板,如果要添加新的
成员函数或者修改现有成员函数的功能,也很方便。而且,模板可以用于创建各种复杂的数据
结构和算法,通过调整模板参数可以满足不同的应用场景。例如,Array类模板可以很容易地
扩展为支持多维数组,或者添加更多的操作函数,如排序、查找等功能。