zoukankan      html  css  js  c++  java
  • 当函数模板遇到普通函数

    先看代码,分析调用情况:

     1 #include<iostream>
     2 
     3 using namespace std;
     4 
     5 template <typename T1,typename T2>
     6 void test_fuc(T1& t1, T2& t2)
     7 {
     8     cout << "template...
    ";
     9 }
    10 
    11 template <typename T>
    12 void test_fuc(T& t1, T& t2)
    13 {
    14     cout << "template...
    ";
    15 }
    16 
    17 void test_fuc(int a, char b)
    18 {
    19     cout << "ordinary fuction...
    ";
    20 }
    21 
    22 int main()
    23 {
    24     int a = 1;
    25     char b = 0;
    26     test_fuc(a, b);
    27     test_fuc(a, a);
    28     test_fuc(b, a);
    29     cout << "hello...
    ";
    30     return 0;
    31 }

    函数模板,也可以重载。当函数模板和普通函数名一样时,调用规则是:

    1.如果普通函数和函数模板都有完全匹配的参数,优先调用普通函数的,如上面26行代码。

    2.函数模板的参数必须严格一致,不能发生隐式转换,但是普通函数可以有隐式类型转换。这个测试需要把上面第一个模板函数屏蔽,调用28行代码,将访问普通函数,因为模板函数不能有隐式转化,必须严格匹配,普通函数则不同。

    3.如果函数模板可以产生一个更好的匹配,优先调用函数模板。具体来说,27行代码,通过隐式类型转化其实是可以调用普通函数的,但是因为有一个完全匹配的模板函数,所以此时优先调用模板函数。

    4.可以通过模板实参列表的语法限定编译器只通过模板匹配。

    举例说明第四点(这也是为什么不动手就学不好c/c++的原因,这个也是因为自己在测试时发现的):

     1 template <typename T>
     2 void test_fuc(T t1, T t2)
     3 {
     4     cout << "template...
    ";
     5 }
     6 
     7 void test_fuc(int a, int b)
     8 {
     9     cout << "ordinary fuction...
    ";
    10 }
    11 
    12 int main()
    13 {
    14     int a = 1;
    15     char b = 0;
    16     test_fuc(a, a);
    17     test_fuc<>(a, a);
    18     //test_fuc<int>(a,a);
    19     cout << "hello...
    ";
    20     return 0;
    21 }

    通过前面的几点分析可以知道,16行的调用将优先匹配普通函数,但要是我们就想调用模板函数,可以像17行那样,加一个空的模板参数列表,让其调用模板函数,也可以显式参数类型,如18行那样都可以让其绕过普通函数而强制调用模板函数。

    再测(注意参数类型我已经更改):

     1 template <typename T>
     2 void test_fuc(T t1, T t2)
     3 {
     4     cout << "template...
    ";
     5 }
     6 
     7 void test_fuc(int a, char b)
     8 {
     9     cout << "ordinary fuction...
    ";
    10 }
    11 
    12 int main()
    13 {
    14     int a = 1;
    15     char b = 0;
    16     test_fuc(a, b);
    17     test_fuc<int>(a, b);
    18     //test_fuc<>(a, b);
    19     cout << "hello...
    ";
    20     return 0;
    21 }

    第16行调用普通函数无可非议,17行,通过模板参数列表强制让其调用int类型的参数,这样也可以调用隐式转化过的模板函数,上面说的模板函数不能隐式转化,必须完全匹配是建立在隐式调用模板函数的前提下,通过模板参数列表显式调用模板函数,还是可以达到隐式转换的效果。但此时不能用空的模板参数,例如18行那样的调用会报错,要隐式转换你也得提供一个转换类型啊。

    再改:

    1 template <typename T>
    2 void test_fuc(T& t1, T& t2)
    3 {
    4     cout << "template...
    ";
    5 }

    将模板函数参数换成引用,此时上面的代码将报错,不能从char转换到int &,这说明,模板函数的隐式转化和普通函数一样,必须要是可以隐式的类型,我们本就不能把一个char类型的绑定给一个int类型的引用。

    再把上述引用类型改成指针,调用

    test_fuc<int>(&a, &b);

    同样报错,不能从char*转化成int*;可见,隐式类型转化的原则模板函数和普通函数都是需要遵循的。我们可以int和char或者double这样的转换,但是不可以用c++语言不支持的隐式类型转化规则。

  • 相关阅读:
    「JSOI2015」套娃
    「JSOI2015」非诚勿扰
    「JSOI2015」送礼物
    「JSOI2015」子集选取
    「JSOI2015」salesman
    「JSOI2015」字符串树
    [2]树的DFS序
    hdu 6058 Kanade's sum
    UVALive 6907 Body Building
    CF617/E XOR and Favorite Number
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/6572494.html
Copyright © 2011-2022 走看看