模板1.0 -- 模板基本原理

为什么需要模板

我们经常有这样的一种使用的情形,就是我们可能需要设计一个函数,然后函数的参数可能是整形的,也可能是浮点型的,还有可能是其他的类型的,这个时候如果对于每一个类型都写一个函数,未免有点太复杂了

我们有以下几个方法来实现一个函数针对不同的类型都能够实现

法一:通过函数重载实现

比如我们想要写一个相加的函数,我们需要实现函数的重载

int Add(const int a,const int b)
{
    return a+b;
}
double Add(cosnt double a,const double b)
{
    return a+b;
}
char Add(const char a,const char )

缺点分析:
1. 一个类出现时就需要继续重载一个函数
2. 代码的复用率低
3. 如果一个函数只是返回值不同,函数的重载还解决不了问题
4. 如果函数的逻辑错误了,那么所有的函数都需要修改,麻烦

法二:使用公共的基类

我们可以将重复的代码放在一个公共的基类,然后进行一个继承

缺点:
1. 公共的代码放在了基类里面就缺少了类型检查的优点了
2. 一个简单的函数,以后使用了继承之后,以后维护起来麻烦

法三:使用宏函数

#define Add(a,b) ((a)+(b))

缺点:
1. 没有了类型检查
2. 在预处理阶段就被替换掉了,不方便调试

引入模板

C++为了解决上面的问题,于是就引入了模板的使用,像下面的形式来实现Add函数的复用

template<class T>
T Add(const T& a,const T&b)
{
    return a+b;
}

其中我们使用class的时候,也是可以使用typename这个关键字的
我们在其他的地方调用这个模板函数的时候,就可以使用下面的方式进行一个调用的过程

int x = 1;
int y = 2;
double m = 1.0;
double n = 2.0;

Add(x,y);
Add(m,n);

上面的两次对模板函数的调用是不是调用的同一个函数呢,答案:不是。他们调用了不同的函数,这里引入的一个概念就是模板的实例化
我们经常听到的一个概念是对象的实例化,就是我们拿一个类去实例化一个对象,比如我们使用下面的代码去实例化一个string的对象

string str;

同样的我们的模板也是有实例化的一个过程的,就是在我们调用我们函数的时候,根据我们的参数进行一个推演,比如刚刚的那个Add(x,y);这个 时候编译器会根据参数的类型,实例化生成一个参数是整形的Add函数,然后在对他进行一个调用,这个就是简单的实例化的过程。

所以说上面的两次调用实际上是生成了不同的函数,然后进行的一个调用的过程

小问题

问题一:模板函数和实例函数共存

还是上面Add函数,如果我们这个时候在上面的模板函数的基础之上又实现了一个函数,这个时候会如何调用呢

int Add(const int& a,const int& b)
{
    return a+b;
}

在这种情况下,如果我们有已经实例化的函数,这个时候会直接调用我们已经实例化的函数,如果没有已经 实例化的函数,这个时候才会去找我们的模板函数,然后实例化一个函数进行一个调用的过程

问题二:模板函数和实例函数参数不匹配

还是上面的程序,我们即有了一个模板函数,又有了一个实例函数,这个时候我们在使用的时候,传递的参数不是两个整形而是两个双精度浮点型,那么这个时候是如何调用的呢

double a = 1.0;
double b = 2.0;
Add(a,b);

这个时候会检查我们的实例函数,但是参数的类型不匹配,所以实际上是生成了一个参数是double类型的模板函数,然后再进行函数的一个调用的过程

如果我们的参数一个是int,一个是double的,这个时候又是怎么样的呢,由大家自己去验证吧

这里我们还需要注意的一个问题就是,实例化函数中的第二个参数不是一个const的时候,这个时候,我们的給 我们的参数传入的是一个double的变量的时候,会发生隐式类型的转换的,这个时候会生成一个临时的变量,这个临时的变量具有常性,所以我们应该在参数上面加上一个const

问题三:模板实例化和类型检查

我们知道我们的模板函数只有在实例化的时候,才会生成可执行代码的,如果我们在VS下面测试的时候,编译器是不会对模板函数的内部进行检查的,比如我们少写了一个分号,但是在linux下面使用g++进行 编译的时候是会进行一个检查的过程的

模板类

模板类也很容易实现,只不过在使用的时候,我们需要对模板类进行一个显式的实例化的过程

template<class T>
class Arr
{
    public:
        Str()
        :_a(a)
        {}
    private:
        T _a;
}


Arr<int> arr;

上面的调用就是一个显式的实例化的过程

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
DUXCMS是一款基于PHP MYSQL运行的开源建站系统,程序采用CANPHP框架编写,特别合适大小型公司企业、政府等使用。 程序特点: 1、小巧易用,程序压缩后大小只有1M左右,虽小功能却不简单,且尽可能的减少您的操作繁琐。2、功能实用,程序提供了基本企业站的实用功能,没有过多的多余功能,极大的方面了用户快速掌握程序的使用。3、多点缓存,程序采用数据库、模板、静态等缓存免去了生成静态的麻烦且访问效果和静态一样快速。4、简单的模板开发,程序采用了独有的模板标签来分离程序和界面的开发,标签简单易用让你快速开发出心仪的界面。5、附加模型字段,使用程序中往往会有多的字段需要使用比如产品编号等,这些可以使用附加模型来解决多余的字段功能。6、多功能表单,用户在后台可生成自己想要的表单功能,如留言板、友情链接、订房、表单反馈等,极大的减少了自主开发功能的难度。7、强大的技术支持,程序基于canphp框架结构编写,框架拥有完善的文档和帮助支持,使您二次开发、插件开发得心应手。8、开源免费,源码完全无加密开发,免去了您的后顾之忧,程序可免费无限制使用,但是禁止包皮发布。 运行环境: 操作系统:windows/linux/macosx服务器环境:apache2.X/IIS5 /NGNIX(需要开启INFO模式支持)PHP版本:5.2/5.3MYSQL版本:5.1及以上
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值