【 声明:版权所有,欢迎转载,请勿用于商业用途。  联系信箱:feixiaoxing @163.com】

如果类是一种确定的数据类型,那么模板就是一种对类的抽象。假设有这么一种类,它需要进行数据的计算,而且类型还很多,那么我们可能就要针对不同类型的数据定义不同的类。我们可以用下面一段代码说明问题:
class int_process
{int a;int b;
public:int_process(int m, int n):a(m), b(n) {}~int_process() {}int add() {return a + b;}int sub() {return a - b;}int mul() {return a * b;}int div() {return a / b;}
};class short_process
{short a;short b;
public:short_process(short m, short n):a(m), b(n) {}~short_process() {}short add() {return a + b;}short sub() {return a - b;}short mul() {return a * b;}short div() {return a / b;}
};

上面的代码内容其实比较简单,大家可以看明白。第一个类是int_process,主要是整数的加、减、乘、除的计算。第二类是short_process,主要处理的短整数的加、减、乘、除计算。两个类处理的内容其实非常相似。那么有没有一种简单的办法可以同时处理这两个类?有!这就是模板。我们可以把具体的数据类型抽象出来,形成一种新的类模式。这就是模板类。下面的代码就是模板类:

template <typename type>
class data_process
{type a;type b;
public:data_process(type m, type n):a(m), b(n) {}~data_process() {}type add() {return a + b;}type sub() {return a - b;}type mul() {return a * b;}type div() {return a / b;}
};

我们看到类把具体的数据类型都抽象成了type。至此,不管是输入值、输出数值,我们都换成了type。至于类的名称,我们也从原来特定的数据类型计算,转变成了通用的data_process,当然这种名称的定义不是太重要的。那么模板类定义之后,我们应该怎么应用呢?大家继续看代码:

void process()
{data_process<int> d(1,2);data_process<char> m('1', '2');data_process<double> p(1.2, 2.3);
}

大家从上面的代码也看的出,模板类的定义并不复杂,只是在模板类的名称之后添加一下具体的数据类型就可以了。如果是int类型的,那么处理int的数据;同理,如果处理的是char或者是double类型数据,我们就可以按照char或者是double类型的数据进行计算,十分方便。当谈,处理的数据远远不止C++语言本身定义的char、double、float、int、short、long这几种数据类型,如果type本身就是一种class类型,同时这样class类型也支持+、-、*、/运算,那么本身也是可以用作模板的。我们这里介绍int、char、double只是为了简单地说明问题。看到类的声明后,我们不禁有一个疑问,既然模板类只有一个,那么这些模板类的构造函数、析构函数、成员函数的处理都相同吗?我们不妨看看看一看他们的汇编代码:

60:       data_process<int> d(1,2);
0040126D   push        2
0040126F   push        1
00401271   lea         ecx,[ebp-14h]
00401274   call        @ILT+45(data_process<int>::data_process<int>) (00401032)
00401279   mov         dword ptr [ebp-4],0
61:       data_process<char> m('1', '2');
00401280   push        32h
00401282   push        31h
00401284   lea         ecx,[ebp-18h]
00401287   call        @ILT+55(data_process<char>::data_process<char>) (0040103c)
0040128C   mov         byte ptr [ebp-4],1
62:       data_process<double> p(1.2, 2.3);
00401290   push        40026666h
00401295   push        66666666h
0040129A   push        3FF33333h
0040129F   push        33333333h
004012A4   lea         ecx,[ebp-28h]
004012A7   call        @ILT+60(data_process<double>::data_process<double>) (00401041)
004012AC   mov         byte ptr [ebp-4],2
63:       int i_d = d.add();
004012B0   lea         ecx,[ebp-14h]
004012B3   call        @ILT+70(data_process<int>::add) (0040104b)
004012B8   mov         dword ptr [ebp-2Ch],eax
64:       char c_m = m.add();
004012BB   lea         ecx,[ebp-18h]
004012BE   call        @ILT+80(data_process<char>::add) (00401055)
004012C3   mov         byte ptr [ebp-30h],al
65:       double d_p = p.add();
004012C6   lea         ecx,[ebp-28h]
004012C9   call        @ILT+75(data_process<double>::add) (00401050)
004012CE   fstp        qword ptr [ebp-38h]
66:
67:   }
上面的代码有点长,我们大家来一起看一下:
60句: 定义int型的class类型,可以看到data_process<int>构造函数地址是0x401032
61句: 定义char型的class类型,看到data_process<char>构造函数地址是0x40103c
62句:定义double型的class类型,看到data_process<double>构造函数地址是0x401041
63句:调用data_process<int>的add成员函数,地址为0x40104b 
64句:调用data_process<char>的add成员函数,地址为0x401055
65句:调用data_process<double>的add成员函数,地址为0x401050
上面的代码表明,其实编译器为我们函数中出现的每一个具体类实例化了一遍。针对每一个类型,模板的构造函数、析构函数、成员函数都要独立生成,这从上面的函数地址就可以看出来,没有什么神奇的。所以,我们明白了模板的本质就是对不同数据类型的相似性操作进行共同属性提取,合成模板。在应用的时候,编译器根据我们使用中的数据类型独立生成每一个类,构建每一个基本运算变量和运算函数,仅此而已。
模板注意事项:
(1)class上出现的问题在模板类上都会出现
(2)先把class写好,然后再转变成模板类
(3)如果不是数据类型的差异,而是共有数据数量上的差异,请选用继承代替模板
(4)模板中的type可以是自定义类型
(5)模板代码只能出现在头文件中,出现在*.cpp文件中没有意义,单独的*.cpp模板代码因为没有涉及具体类型,因此不会编译成任何二进制代码
(6)不同版本的vc对模板支持有差异,编译错误不一定是你自己的原因,但是绝大部分应该是你的原因
(7)模板生成的告警很冗长,一个warning或者是error 30~50行很正常,不要害怕,孰能生巧
【预告: 下面的博客介绍模板函数】

用汇编的眼光看C++(之模板类)相关推荐

  1. 用汇编的眼光看C++(之 总结篇)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 早在八月份的时候,就陆陆续续写了二十多篇用汇编语言看C++的博客内容.在此为了做一个概括,也为 ...

  2. 用汇编的眼光看C++(之退出流程)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 无论是在判断还是在循环的过程中,通常在遇到合适的条件的时候就会退出相应的模块.跳出模块运行的方 ...

  3. 用汇编的眼光看C++ (之x86汇编)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 说到用汇编的眼光看C++语言,那么怎么阅读汇编代码就成了我们需要解决的一个问题.其实,实话说, ...

  4. 从汇编的眼光看C++(之递归函数与模板类)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 递归,相信有过基本C语言经验的朋友都明白,就是函数自己调用自己.所以,本质上说,它和普通的函数 ...

  5. 用汇编的眼光看c++(之模板函数)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com]  如果说模板类定义的是一种数据类型,那么模板函数定义的就是一种函数.既然是函数,那么就有输入数 ...

  6. 用汇编的眼光看C++(之缺省模板、特化模板)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 缺省函数是C++的一个基本特色.缺省函数定义比较简单,也就是说,对于函数的某一个输入参数或者几 ...

  7. 用汇编的眼光看C++(之const属性)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] const是C/C++语言中的关键字,但是如果用的好,可以极大地提高代码的健壮性.一般来说co ...

  8. 用汇编的眼光看C++(之判断流程)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 在我们平常的编程当中,用于判断的地方很多,但主要有下面三种方式:if-else:switch: ...

  9. 用汇编的眼光看C++(之拷贝、赋值函数)

    拷贝构造函数和复制函数是类里面比较重要的两个函数.两者有什么区别呢?其实也很简单,我们可以举个例子,加入有这样一个类的定义: [cpp] view plaincopy class apple { pu ...

最新文章

  1. spring外部化配置
  2. linux相等路径,关于linux:如何检查Bash中两条路径是否相等?
  3. SGI重获新生 有望下月摆脱破产保护
  4. MySQL 性能优化技巧(一)
  5. 调用WCF返回Josn的两种方式
  6. linux之V4L2摄像头应用流程
  7. iOS核心动画之CALayer(1)
  8. 5G 比 4G 快,不只是因为......
  9. GitLab轻松创建一个Merge Request
  10. 数据创建表 修改列 新增列
  11. CCIE学习(31)—— RIP知识回顾
  12. linux/unix编程手册-6_10
  13. 盒子浮动的重要性及对其它元素的影响
  14. android系统平板输入法切换,安卓平板电脑怎么样切换输入法?
  15. 关于canvas的学习心得(三)(计算错误)
  16. 语音信号调制matlab,第二章 语音信号的数字模型 数字语音处理及MATLAB仿真 教学课件.ppt...
  17. 数学建模养老保险问题matlab,全国大学生数学建模竞赛C题 企业退休职工养老金制度的改革...
  18. latex 参考文献显示问号_终于用回vscode写LaTeX了
  19. 异常值 识别与处理方法
  20. 新网站如何提交链接让百度更快速的收录

热门文章

  1. PHP 长连接,奏是这么简单
  2. STL库的内存配置器(allocator)
  3. VS2005+SQL2005 Reporting Service动态绑定报表(Web)
  4. 使用webService时,gsoap数据类型注意事项
  5. 【Python3爬虫】微博用户爬虫
  6. 【Android界面实现】Drawable Animation 使用介绍
  7. 南海区行政审批管理系统接口规范v0.3(规划) 2.业务申报API 2.1.businessApply【业务申报】...
  8. 对于response.setContentType(MIME)的解释
  9. ListView原理
  10. php随笔11-Thinkphp常用系统配置大全