• c/c++ 模板函数的重载


    模板函数的重载

    普通函数可以重载,模板函数也可以重载,但规则复杂

    有下面2个函数,名字相同,返回值相同就,参数不同,符合重载。

    template<typename T>
    std::string moban(const T& t){}
    template<typename T>
    std::string moban(T* p){}
    

    调用1

    std::string s("hi");
    std::cout << moban(s) << std::endl;
    

    结果1:调用的是(const T& t),这个可以简单理解,因为参数不是指针类型,所以不适用于(T* p)。

    调用2

    std::string s("hi");
    std::cout << moban(&s) << std::endl;
    

    结果2:调用的是(T* p)。这个就复杂了,因为2个模板都符合,但是调用哪个呢。

    • moban(const string*&) T被绑定到string*。
    • moban(string*) T被绑定到string。

    因为(const T& t)的实例需要进行普通指针到const指针的转换,(T* p)不需要转换,所以是更精准的匹配。

    所以推导出规则1:更精准的匹配会被优先采用。

    调用3

    std::string s("hi");
    const std::string* sp = &s;
    std::cout << moban(sp) << std::endl;
    

    结果3:调用的是(T* p)。这个就更复杂了,因为2个模板都符合,而且都是同样精准的匹配,但是调用哪个呢。

    • moban(const string*&) T被绑定到string*。
    • moban(string*) T被绑定到const string。

    在此情况下,因为是同样精准的匹配,所以无法区分调用哪个。但是根据重载函数模板的特殊规则,调用了(T* p)。

    原因是,(const T& t)本质上可以用于任何类型,包括指针类型,比(T* p)更通用,后者只能用于指针类型。

    所以推导出规则2:同样精准的话,更特殊的会被优先采用。

    如果非模板函数和模板函数同时存在,构成重载,会调用哪个?

    有下面3个函数,名字相同,返回值相同就,参数不同,符合重载。

    template<typename T>
    std::string moban(const T& t){}
    template<typename T>
    std::string moban(T* p){}
    std::string moban(const std::string& s){}
    

    调用4

    std::string s("hi");
    std::cout << moban(s) << std::endl;
    

    结果4:调用的是非模板的函数。

    • (const T& t) T被绑定到string,也是可以被调用的。

    但是,非模板优先模板。

    所以推导出规则3:非模板和模板同时都适用的时候,非模板的会被优先采用。

    调用5

    std::string s("hi");
    std::cout << moban(s) << std::endl;
    

    结果5:调用的是(T* p),而没有调用非模板函数。

    所以看出来,规则3有个特例,就是,如果模板的匹配比非模板的匹配更精准的时候,模板会被优先采用。

    • moban(const T& t) T被绑定到char[2]。
    • moban(T*) T被绑定到const char。
    • moban(const std::string& s) 要求从const char*到string的类型转换。

    理由:非模板也是可行的,但是需要进行一次用户定义的类型转换,因此她没有模板的匹配更精准。但是2个模板都可以被调用,但是(T*)更特例化,所以最好调用的是(T*)

    所以推导出规则4:非模板和模板同时都适用的时候,非模板如果需要一次用户定义的类型转换,而模板不需要的话,模板会被优先采用。

    非模板函数和模板函数的声明位置,导致结果的不同。

    有下面4个函数,名字相同,返回值相同就,参数不同,符合重载。

    template<typename T>
    std::string moban(const T& t){}
    template<typename T>
    std::string moban(T* p){}
    
    std::string moban(const char* p){
      return debug_rep(std::string(p));
    }
    std::string moban(const std::string& s){}
    

    调用5

    std::cout << moban("hello") << std::endl;
    

    结果5:首先调用的是(const char* p),这是没有疑问的,它是最匹配的,问题是它里面的return debug_rep(std::string(p));调用的是哪个呢?调用的是:(const T& t)。

    分析:由于非模板的(const std::string& s)的定义在,(const char* p)的后面,所以return debug_rep(std::string(p));只能看到它前面的2个模板函数,所以匹配了(const T& t)。如果把(const std::string& s)的定义放在,(const char* p)的前面,return debug_rep(std::string(p));调用的就是非模板的(const std::string& s)。

    c/c++ 学习互助QQ群:877684253

    本人微信:xiaoshitou5854

  • 相关阅读:
    Python即时网络爬虫项目启动说明
    Spring Cloud Consul入门
    Selenium用法示例
    云中漫步,做个公众号方便生活、取悦自己
    PhantomJS用法示例
    Python3环境安装PySpider爬虫框架过程
    Python3环境安装Scrapy爬虫框架过程及常见错误
    爬虫扒下 bilibili 视频信息
    Sql优化(一) Merge Join vs. Hash Join vs. Nested Loop
    email.py
  • 原文地址:https://www.cnblogs.com/xiaoshiwang/p/10320549.html
Copyright © 2020-2023  润新知