c++ template使用疑问

具体template使用网上可以看到说明,在这里强调一点关于template模版实参为空的特例。 转载网络关于c++考级的要点. 知识点4:


    1.1  函数模板

  1.1.1  考点1:函数模板的概念和声明

    函数模板是一系列相关函数的模型或样板,这些相关函数的源代码形式相同,只是所针对的数据类型不同。对于函数模板,数据类型本身成了它的参数,因而是一种参数化类型的函数。类的成员函数也可以声明为函数模板。
    声明一个函数模板的格式如下:
    template <模板形参表声明>
    返回类型 函数名(函数形参表)
    {
       …… //函数体
    }

    其中,<模板形参表声明>是由一个或多个“模板形参”组成的,如果是多个,则要用逗号隔开。“模板形参”具有下面3种形式:

      typename 参数名
      class 参数名
     类型修饰 参数名

    这里的参数名可以是任意合法的C++标识符。前两种形式是等价的,也就是说,在声明模板形参时,关键字typename和class可以互换。用typename或class声明的参数称为虚拟类型参数;而用“类型修饰”声明的参数则称为常规参数。这里的“类型修饰”是指具体的数据类型(如int、double、char等)。函数模板的<模板形参表声明>中,一定要包含虚拟类型参数,而常规参数则可以根据实际需要选择。

    <模板形参表声明>中声明的虚拟类型参数可以用做:

     函数的返回值类型
     函数的形参的类型
     函数体内变量的类型

       例1.1.1  下列是模板声明的开始部分,其中正确的是(   )。
    A.template <T>            B.template <class T1,T2>
    C.template <class T1,class T2>     D.template <class T1;class T2>
    答案:C

       例1.1.2  下面的函数模板定义中错误的是(   )。
    A.template<class Q>       B.template<class Q>
       Q F(Q x){return Q+x;}         Q F(Q x){return x+x;}
    C.template<class T>       D.template<class T>
       T F(T x){return x*x;}         bool F(T x){return x>1;}
    解析:各个选项中声明的Q和T都是虚拟类型参数。函数模板形参表中声明的虚拟类型参数可以用做:
     函数的返回值类型
     函数的形参的类型
     函数体内变量的类型
    选项B、C和D符合以上三种用法。而选项A让虚拟类型参数Q直接参与运算是错误的。虚拟类型是具体类型(如int型,double型等)的抽象。我们知道,int本身并不能直接参与数学运算,但是由它定义的int型变量或int型参数可以直接参与运算。虚拟类型Q和T本身也不能直接参与运算,但是由它们定义的“T类型”或“Q类型”的参数x可以参与运算。所以,选项A中“Q+x”的表达是错误的。
    答案:A
1.1.2  考点2:模板函数

    函数模板中声明的函数称为模板函数。
    调用一个模板函数的格式如下:
    函数名 <模板实参表> (函数实参表);
    
    函数名(函数实参表);
    第二种格式中省略了所有的模板实参,使用这种格式是需要一定条件的(详见考点4)。
    类模板的成员函数都是模板函数。

       例1.1.3  以下函数模板max的功能是:返回数组a中最大元素的值。请将横线处缺失部分补充完整。
    template <typename T>
    T max (T a[], int n)
    {
     T m = a[0];
     for (int i = 1; i < n; i++)
        if (a[i]>m)          ;
        return m;
    }
    解析:本题考查模板函数的定义。在编写函数体时,模板函数与普通函数是一样的。根据题意,返回的m值应该是a中最大元素的值,所以当a[i]>m时,应该将较大的a[i]值赋给m。在遍历数组a[]后,最终m就保存了数组a[]中最大元素的值。
1.1.3  考点3:函数模板的实例化

    在调用模板函数时,编译系统依据实际所使用的数据类型生成某个具体函数定义的过程称为函数模板的实例化。在实例化过程中,是用实际类型(如int、long等)替代虚拟类型的。
    实例化的过程或结果通常是看不见的,编译系统会根据函数调用的具体情况自动传递相应的模板实参,生成相应的函数实例。每一个实例就是一个函数定义。
    实例化过程中,除了可以用各种具体的C++固有数据类型取代虚拟类型,还可以用某些用户自定义类型来取代虚拟类型,这里的自定义类型包括结构体以及某些用户定义的类。

       例1.1.4  下列程序的输出结果是        。
    #include <iostream>
    using namespace std;
    template <typename T>
    T fun (T a, T b) {return (a<=b)?a:b;}
    int main()
    {
       cout<<fun(3,6)<<','<<fun(3.14F,6.28F)<<endl;
       return 0;
    }
    解析:本题定义了一个模板函数fun,其形参a、b及函数返回类型均为T类型。函数fun的功能是返回a、b中数值较小的数。在main函数中,第一次调用fun时,实际上是调用了“int fun(int a,int b)”这个函数,故返回整型数据“3”。第二次调用时,实际上是调用了函数“float fun (float a, float b)”,返回浮点型数据“3.14”。
    答案:3,3.14

    1.1.4  考点4:模板实参的省略

    在调用模板函数时,编译系统需要足够的信息来判别每个虚拟类型参数所对应的实际类型,可以从两个不同的渠道获得信息:从“模板实参表”(在“<”和“>”之间)或从模板“函数实参表”(在“(”和“)”之间),“模板实参表”的信息优先于“函数实参表”的信息。如果从后者得到的信息已经能够判断其中部分或全部虚拟类型参数所对应的实际类型,而且它们又正好是“模板形参表声明”中最后的若干参数,则在“模板实参表”中可以省略这几个参数。如果所有的模板实参都被省略了,则空表“<>”也可以省略。

    但在以下情况中,模板实参是不能省略的。

    ① 从模板“函数实参表”中获得的信息有矛盾。例如,当编译系统从某一个函数实参中获得的信息是虚拟类型参数T(假设为T)对应的实际类型为int,可是从另一个函数实参中获得的信息却是虚拟类型参数T对应的实际类型为double时,就产生了矛盾。T不可能同时为
int和double型,这将导致编译器无法找到匹配的函数模板的定义,编译时报错。解决这一问题的方法之一就是显示给出虚拟类型参数T对应的模板实参,强制T对应于int或是double。
    ② 虚拟类型参数用做函数的返回值类型,而且函数需要返回特定类型的值,而不管函数实参的类型是什么。在这种情况下,需要用模板实参强制虚拟类型参数对应于特定类型。
    ③ 虚拟类型参数没有出现在模板的“函数形参表”中。此时无法从模板的“函数实参表”中获取对应的信息,因而不能省略模板实参。
    ④ 函数模板含有常规形参。常规参数是用具体的类型修饰符(如int、double、char*等)定义的,对应的实参必须是常量表达式。因此,常规参数的信息无法从模板的“函数实参表”中获得,调用模板函数时必须显示给出对应于常规参数的模板实参。

       例1.1.5  有如下函数模板定义:
    template <class T>
    T func (T x, T y){ return x*x+y*y;}
    在下列对func的调用中,错误的是(   )。
    A.func(3,5);    B.func(3.0,5.5);  C.func(3,5.5);  D.func<int>(3,5.5);
    解析:对于本题中定义的模板函数,如果用选项C中“func(3,5.5);”的形式来调用,在编译时会出现“template parameter 'T' is ambiguous,could be 'double' or 'int' ”的错误,也就是说T对应的实际类型是不明确的。编译系统从第一个参数“3”获得的信息是“T对应于int”,而从第二个参数“5.5”处获得的信息是“T对应于double”,二者相互矛盾,因而编译时产生错误。
    选项D中提供了模板实参<int>,因为模板实参优先于函数实参,所以T对应的实际类型是明确的,在这里就是int型。在调用过程中,double型的参数“5.5”将被自动转换成int型。
    选型A和B所提供的两个函数实参的类型是一致的,不存在矛盾。
    答案:C

       例1.1.6  有如下函数模板声明:
    template <typename T>
    T Max(T a,T b) {return (a>=b)?a:b;}
    下列对函数模板Max的调用中错误的是(   )。
    A.Max(3.5,4.5)            B.Max(3.5,4)
    C.Max<double>(3.5,4.5)      D.Max<double>(3.5,4)
    答案:B


<think>好的,用户让我介绍一下C++函数模板的最简单使用。首先,我需要确定用户的知识水平。可能他们刚学C++,对模板还不熟悉,所以要从基础讲起。 用户需要的是“最简单使用”,所以例子要简单明了,避免复杂的术语。可能需要先解释什么是函数模板,然后给出一个例子,说明如何声明和调用。 函数模板的作用是让同一个函数处理不同类型的数据,比如交换两个变量或者返回最大值。比如max函数,可以比较int、double等类型。我应该用一个简单的例子,比如交换或者加法,这样用户容易理解。 接下来,考虑如何分步骤讲解。首先用template关键字声明模板类型T,然后定义函数。然后展示如何调用,自动推导类型或者显式指定类型。 可能用户会有疑问,比如为什么要用模板而不用函数重载?需要简单说明模板的优势,减少代码重复。不过用户的问题是最简单使用,可能暂不需要深入讨论。 还要注意语法细节,比如模板参数列表、函数参数和返回类型。确保例子没有错误,比如正确的尖括号和分号。 然后,考虑用户可能的误区,比如模板实例化的机,或者类型推导失败的情况。但作为最简单的介绍,这些可能暂不用提,保持回答简洁。 最后,检查例子是否能够编译运行,确保正确性。比如swap例子中的引用参数,确保用户不会因为值传递而出错。 总结:用swap或max作为例子,分步骤说明模板的声明、定义和调用,强调泛型编程的好处,保持语言简单易懂。</think>C++ 函数模板最简单的使用示例: ```cpp #include <iostream> using namespace std; // 定义函数模板(泛型交换函数) template <typename T> void mySwap(T &a, T &b) { T temp = a; a = b; b = temp; } int main() { // 自动类型推导调用 int x = 10, y = 20; mySwap(x, y); // 编译器自动识别为int类型 cout << x << " " << y << endl; // 输出:20 10 // 显式指定类型调用 double m = 3.14, n = 6.28; mySwap<double>(m, n); cout << m << " " << n << endl; // 输出:6.28 3.14 return 0; } ``` **关键点说明:** 1. `template <typename T>` 声明模板类型(`T` 是占位符类型) 2. 函数参数和返回值都可以使用 `T` 3. 调用可让编译器自动推导类型,或用 `<具体类型>` 显式指定 4. 适用于所有支持函数内操作的类型(如这里的赋值操作) **另一个简单示例(求最大值):** ```cpp template <typename T> T getMax(T a, T b) { return (a > b) ? a : b; } // 使用: cout << getMax(5, 9); // 输出9 cout << getMax(3.14, 2.99);// 输出3.14 ``` **优势:** 避免为不同类型重复编写相同逻辑的函数,实现代码复用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值