



免费预览已结束,剩余1页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
不知道为什么,我最近越来越觉得C+太难了,也许是因为我也陷入到扣语言细节的泥沼了吧。不过换个角度来讲,C+之所以这么有吸引力,也多亏了它有这么多复杂的细节,正是因为这些细节不断被发掘,才更加引得C+程序员激情四射、奋不顾身。比如说模板元编程,C+模板在设计之初根本没有想到模板元编程这回事,更没想到C+模板系统是图灵完备的,结果1994年Erwin Unruh提数了可以使用模板在编译器进行某些计算后,无数的大牛人便前仆后继,将模板编程发挥到了极致。我想我也是属于那种没事找抽的人,要不然我为什么会抱着C+ Templates这本书看呢?奈何我能力有限,兼且经验不足,使用C+的时候少,使用模板的时候更少,所以对于书中的内容,要么就是看了不是很懂,要么就是看了也不知道它有什么用。但是也不是完全没有收获,对于以前两个百思不得其解的问题,也还算是灵光一闪、豁然贯通了。其中一个是Trait,这是我以前在使用STL和ATL库的时候遇到过的,虽然想不透其中的奥妙,但是不影响我写程序。另外一个是模板元编程,只听说过,如雷灌耳,但是却从来没有见过,也想象不出它的原理,C+ Templates终于让我看到了它的庐山真面目。先来说说Trait,这是一个在C+ Template编程中经常用到的一个设计机制,我在使用STL库中的basic_string时见到过,其定义如下:template class CharType, class Traits=char_traits, class Allocator=allocator class basic_string其中就有一个模板参数为Traits,而它的默认值为char_traits,这里的char_traits就是一个trait类,它可以提供关于CharType的特征信息。我们常用的string类的定义如下:typedef basic_string string如果我们把它的默认模板参数带入,就可以看到string的形式是这样的:basic_string char, char_traits, allocator 到这里,我就迷糊了,我在想,为什么char_trait就能够取得char的类型信息?为什么basic_string就不行?难道说加上trait这几个字,模板类就有了三头六臂不成?另外一个见到Trait的地方就是ATL 3.0中的窗口类,这是我很早以前翻译的一篇文章,其中也使用到了Trait,在定义窗口样式的时候,其代码如下:class CMyWindow: public CWindowImpl CMyWindow, CWindow, CWinTraits ;当时我就想了,为什么不直接把“WS_OVERLAPPEDWINDOW|WS_VISIBLE,0”当成模板参数传递给CWindowImpl算了,还非要CWinTraits来掺和一把?直到现在,我终于知道,原来一直错的就是我。我不该把char_traits看成是一个模板类,不该认为传给它一个char它就可以读出char的特征信息,传给它一个int它就能读出int的特征信息。它当然不可能具备这么高级的功能,更不可能加上traits几个字就一下子挣脱了C+语言的束缚。那么不把它看成一个模板类,应该怎么看呢?应该把char_traits看成一个整体,说专业点,那叫模板特化,说通俗点,就是原来这里面的特征信息都是编写它的人自己定义的,如果你要让basic_string能够处理int,double之类的信息,你还得自己写一个char_traits和一个char_traits。CWinTraits也同样是这个道理。为了说得更清楚点,我这里举个小例子。什么例子呢?就写个计算平均值的模板函数吧,如下:template T average(T const* begin, T const* end) T total = T(); int count = 0; while (begin != end) total += * begin; +begin; +count; return total/count;下面是使用这个函数的代码,如果我们计算的类型是int,结果是正确的,如下:int main() int numbers = 1,2,3,4,5; std:cout average(&numbers0,&numbers5) std:endl;该程序运行的结果是3,非常正确,将数据类型换成float,double也没有问题。但是,如果是char类型,就不一定了。代码如下:int main() char characters = traits; std:cout static_cast(average(&characters0,&characters6) std:endl;运行结果为 -17,不信大家可以自己运行试一下。为什么是个负数呢?原因是因为char类型能表示的范围只有-127到+128,几个字母一加,就溢出了。为了得到正确的结果,我们希望能有一种机制,来指定运算的时候用什么作为返回类型,这时候,traits就可以闪亮登场了。前面已经说过,要把trait看成一个整体,所以应该为每一个数据类型都定义一个trait。在这个例子中,我们主要是为了对每一个运算的类型指定合适的返回类型,任务比较简单,所以,代码可以这样写:template class TypeTraits;template class TypeTraitspublic: typedef int ReturnType;template class TypeTraitspublic: typedef int ReturnType;template class TypeTraitspublic: typedef int ReturnType;template class TypeTraitspublic: typedef double ReturnType;函数可以改成这样:template typename Traits:ReturnType average(T const* begin, T const* end) typedef typename Traits:ReturnType ReturnType; ReturnType total = ReturnType(); int count = 0; while (begin != end) total += * begin; +begin; +count; return total/count;使用该函数的代码是这样:int main() int numbers = 1,2,3,4,5; std:cout averageint,TypeTraits (&numbers0,&numbers5) std:endl; char characters = traits; std:cout averagechar,TypeTraits (&characters0,&characters6) std:endl;这时候,一切都正常了。只可惜模板函数不支持默认模板参数,要不然,这里的代码可以更简洁。再来说说Template Mataprogram,中文叫模板元编程。我之能听说它,并对它不甚向往,主要是因为它有这样几个特点:1、它编的程序不是运行的时候执行的,而是在编译的时候由编译器执行的;2、它能够牵着编译器的鼻子走,靠的完全是符合标准的模板语法,不需要使用编译器的任何API;3、它居然是图灵完备的,也就是说它什么事都能干。牛吧?C+提供了一个模板机制,这些大牛们居然可以用模板把编译器耍得团团转,居然能在程序还没运行的时候就什么都能干。反正我是崇拜得五体投地。直到最近看书,才找到了它的奥秘所在,当然了,只限于基本原理。那么,这个基本原理是怎样的呢?其实就是靠的模板的实例化,和使用枚举值或静态常量。具体来说是这样:当编译器遇到enum的定义的时候,就会对该enum进行求值,这个求值是在编译期进行的,而如果该enum对应的表达式是一个模板类的成员,则会实例化该模板类,而实例化模板类的时候,又是递归进行的,这样,就可以在递归的过程中作我们想做的任何事(理论上可以做任何事,但是以我的水平,也就只能算算加减乘除)。看起来是不是不好理解?没关系,下面看一个例子,计算N的阶乘: template class Factorialpublic: enum result = N * Factorial:result ;这下该明白了吧,为了得到Factorial:result的值,就会实例化Factorial,然后又会实例化Factorial,依次类推,一直递归下去。那么什么时候结束呢?所以还需要一个特化版本:templateclass Factorialpublic: enum result = 1 ;下面写几行代码测试一下,如下:int main() std:cout Factorial:result std:endl; return 0;OK,事情就这么简单。大家都知道,递归可以代替循环,就只是对内存的消耗大一些,所以递归的层次不能太多。解决了循环的问题,那么分支结构如何解决呢?不用担心,看看下面这样的模板定义:template class IfThenElse;template class IfThenElsepublic: typedef Ta ResultT;template class IfThenElsepublic: typedef Tb ResultT;一个模板类加上两个局部特化版本就解决了问题,如果第一个模板参数是true,则选择Ta作为结果,否则就选择Tb作为结果。虽然C+为我们提供了模板元编程的能力,
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 合法房屋改造方案范本
- 河南环保钢板仓施工方案
- 女儿墙外墙抹灰施工方案
- 心肺衰竭出院护理查房
- 公民医学素养体系构建
- 小学安全岗位测试题及答案解析
- 销售项目执行方案范本
- 陕西商场宣传栏施工方案
- 安全生产月题库与及答案解析
- 老旧医院拆除方案范本
- 2025-2030滑雪培训行业市场发展分析及前景趋势预测与投资可行性评估报告
- 课堂高效学习的主阵地 教学设计-2023-2024学年高中上学期主题班会
- 2025年放射工作人员培训考试试题(附答案)
- 高考熟词生义解密(复习讲义)-2026年高考英语一轮复习(北京专用)挖空版
- 2025年北京市中考英语试卷(含答案与解析)
- 浙江名校协作体(G12)2025年9月2026届高三返校联考英语(含答案)
- 2025年环保法律法规基础知识考试卷及答案
- 2026届新人教版高考物理一轮复习讲义:静电场及其应用(含答案)
- 检测基础知识培训课件
- 采购管理大师谢勤龙讲义《供应链管理的问题多多与解决之道》
- 国企招聘笔试题及答案-投资专员、投资经理B卷
评论
0/150
提交评论