模板函数的重载

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

有下面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

c/c++ 模板函数的重载的更多相关文章

  1. 聊聊C++模板函数与非模板函数的重载

    前言 函数重载在C++中是一个很重要的特性.之所以有了它才有了操作符重载.iostream.函数子.函数适配器.智能指针等非常有用的东西. 平常在实际的应用中多半要么是模板函数与模板函数重载,或者是非 ...

  2. [C++] 用Xcode来写C++程序[5] 函数的重载与模板

    用Xcode来写C++程序[5] 函数的重载与模板 此节包括函数重载,隐式函数重载,函数模板,带参数函数模板 函数的重载 #include <iostream> using namespa ...

  3. [c++][语言语法]函数模板和模板函数 及参数类型的运行时判断

    参考:http://blog.csdn.net/beyondhaven/article/details/4204345 参考:http://blog.csdn.net/joeblackzqq/arti ...

  4. C++:函数模板与模板函数

    6.1 模板的概念 C++允许用同一个函数定义函数,这些函数的参数个数和参数类型不同.例如求最大值的max函数, int max(int x,int y) {       return (x>y ...

  5. C++模板专门化与重载

    最近在复习C++有关知识,又重新看<<Effective C++>>,收获颇丰.原来以前看这边书,好多地方都是浅尝辄止.<<Effective C++>> ...

  6. [转]C++函数模板与模板函数

      1.函数模板的声明和模板函数的生成   1.1函数模板的声明 函数模板可以用来创建一个通用的函数,以支持多种不同的形参,避免重载函数的函数体重复设计.它的最大特点是把函数使用的数据类型作为参数. ...

  7. C++普通函数与模板函数以及特化函数重载的优先级问题

    在面对C++模板的时候,需要十分注意,因为模板的复杂性有很多情况,所以最好学习模板的方法我个人认为就是用到就去学,用不到就尽量别去看各种奇门怪技,因为你就算看了,好不容易搞懂模板的实现内部了,包括元编 ...

  8. c++模板函数实例化的偏序机制

    一:废话 今天在stackoverflow上看到一个关于c++模板specialization的问题: http://stackoverflow.com/questions/18283851/temp ...

  9. C++ template学习一(函数模板和模板函数)

    函数模板和模板函数(1)函数模板函数模板可以用来创建一个通用的函数,以支持多种不同的形参,避免重载函数的函数体重复设计.它的最大特点是把函数使用的数据类型作为参数.函数模板的声明形式为:templat ...

随机推荐

  1. Android之崩溃日志管理

    文章大纲 一.Android崩溃日志管理简介二.崩溃日志管理实战三.项目源码下载   一.Android崩溃日志管理简介 1. 什么是android崩溃日志管理   开发中有些地方未注意可能造成异常抛 ...

  2. 【Chrome插件】去掉因使用jsonView插件的弹出窗口"请停用以开发者模式运行的扩展程序"

    前言 小编最近使用jsonView插件时,每次打开谷歌浏览器都会弹出下面的窗口,上网搜索,找到一个非常有效的方法. 解决方法 一.新建一个文本文档 二.复制代码 <# : @echo off c ...

  3. sqlserver—数据完整性(理论篇)

    数据完整性主要指的是数据的精确性和可靠性,目的就是为了防止数据库中存放的数值,以及字符具有合法性(即按照管理员定义的规则进行存放) 分为以下四类: 实体完整性 实体完整性要求每一个表中的主键字段都不能 ...

  4. 删除表中多余的重复记录,重复记录是根据单个字段(Id)来判断,只留有rowid最小的记录

    delete from Resource where Title in (select Title from Resource group by Title having count(Title) & ...

  5. SQL Server查看索引重建、重组索引进度

    相信很多SQL Server DBA或开发人员在重建或重组大表索引时,都会相当郁闷,不知道索引重建的进度,这个对于DBA完全是一个黑盒子,对于系统负载非常大的系统或维护窗口较短的系统,你会遇到一些挑战 ...

  6. H5直播避坑指南

    本文来自"小时光茶社(Tech Teahouse)"公众号 作者简介: 文赫,2015年加入腾讯,作为前端开发工程师参与过手Q游戏公会,游戏中心,企鹅电竞等项目,具有丰富的移动端开 ...

  7. Redux进阶(一)

    State的不可变化带来的麻烦 在用Redux处理深度复杂的数据时会有一些麻烦.由于js的特性,我们知道当对一个对象进行复制时实际上是复制它的引用,除非你对这个对象进行深度复制.Redux要求你每次你 ...

  8. Java数据结构和算法 - 二叉树

    前言 数据结构可划分为线性结构.树型结构和图型结构三大类.前面几篇讨论了数组.栈和队列.链表都是线性结构.树型结构中每个结点只允许有一个直接前驱结点,但允许有一个以上直接后驱结点.树型结构有树和二叉树 ...

  9. 带你精读你不知道的Javasript(上)(一)

    斌果在这几天看了下你不知道的js这本书,这本书讲的东西还是挺不错的,其中有很多平时我压根没接触到的概念和方法.借此也可以丰富一下我对js的了解. 第一部分 第一章 作用域是什么? 1.程序中一点源代码 ...

  10. DotNetCore跨平台~认识环境和环境变量

    回到目录 环境 环境,对于开发来说就是部署的一种场景,你可以是调试场景,测试场景,生产场景,当然还可以有很多其它的场景,只要你的项目需要就可以自定义,微软帮我们定义了三种标准的环境变量,下面来说一下. ...