c++模版的一些使用方法(三)
2012-04-21 16:52
309 查看
c++模版的应用是可以分类的。按照用途,可以分为:
1)工程模版
2)算法和数据结构的解耦
3)工作于编译期的模版
4)XX的封装
5)适配器模式
首先解释一下,这里的划分属于较高层的应用划分,但这些应用都是基于模版的一些共同特性的,比如带默认参数、特化和偏特化等。
分别解释一下就是:
(1)工程模版:《c++模版的一些使用方法(一)》中提到修改第三方库的应用属于这一类。工程模版主要是在大工程中的一些处理手法,不太好说。
(2)算法和数据结构的解耦就很清晰了,比如stl库,find算法既可以用于vector也可以用于list。再比如经常使用的单件模式,将它声明为几类,任何需要是单件模式的类只要从这个基类派生即可获得单件属性
(3)工作于编译期的模版
由代码到可执行文件分为几个阶段:
No.1预处理阶段:处理#define,#ifdef,#include等预处理指令。它使在编译之前提供了一次修改源文件的机会,具有很大的灵活性。
No.2编译期:将源代码编成机器码,每个模块生成obj文件,
No.3链接器:将n个obj文件组合在一起,解析他们之间的交叉关系,得到可执行文件。
平时我们所说的执行效率,是指可执行文件处理一组数据的效率,可能还听说过在程序设计比赛中可以利用预处理来做一些事情,以此减少程序处理数据的时间,那么同样,有些事情是可以在编译期做的,同样可以通过把一些事情提前到编译期来提高程序的效率。
首先要明白哪些工作可以在编译期做:
No.1当有函数重载时,编译器在编译期决定调用哪个函数;
No.2sizeof操作符,typedef操作符,+ - = < > :?等运算符,等等等
No.3enum类型的赋值
No.4模版的特化、偏特化和实例化
那么,可以在编译期做哪些事呢?
我总结的有两点:
1)计算一些数据
2)生成代码
计算数据时,比如,可以这样计算Fibonacci数列:
上面Fiboncaai<40>输出的结果是102334155,反汇编看一下,如图:
编译器经过计算,直接在这里放了一个立即数,译成十进制正是102334155。
而上面代码中所消耗的时间是0。如图
而经过测试,用普通的函数递归计算Fiboncaai的第40个,需要8秒的时间。
用于生成代码时,也可以成为模版的元编程,元编程是指某类计算机程序的编写,这类计算机程序编写或者操纵其他程序(或者自身)作为它们的数据,或者在编译时完成部分本应在运行时完成的工作。很多情况下比手工编写全部代码相比工作效率更高。编写元程序的语言称之为元语言,被操作的语言称之为目标语言。一门语言同时也是自身的元语言的能力称之为反射。
由上面的定义可知,元编程也是工作在编译期,其实上面的计算数据的应用,也可以归为元编程,因为编译器不断的实例化模版来“递归”,本质上也是在帮我们生成代码。Loki库中的Typelist就是使用模版元编程的经典之作。
XX的封装和适配器模式以后再说吧
1)工程模版
2)算法和数据结构的解耦
3)工作于编译期的模版
4)XX的封装
5)适配器模式
首先解释一下,这里的划分属于较高层的应用划分,但这些应用都是基于模版的一些共同特性的,比如带默认参数、特化和偏特化等。
分别解释一下就是:
(1)工程模版:《c++模版的一些使用方法(一)》中提到修改第三方库的应用属于这一类。工程模版主要是在大工程中的一些处理手法,不太好说。
(2)算法和数据结构的解耦就很清晰了,比如stl库,find算法既可以用于vector也可以用于list。再比如经常使用的单件模式,将它声明为几类,任何需要是单件模式的类只要从这个基类派生即可获得单件属性
template<typename T> class Singleton { protected: Singleton(){} public: static T& GetInstance() { static T Instance; return Instance; } }; class MyClass:public Singleton<MyClass> {};
(3)工作于编译期的模版
由代码到可执行文件分为几个阶段:
No.1预处理阶段:处理#define,#ifdef,#include等预处理指令。它使在编译之前提供了一次修改源文件的机会,具有很大的灵活性。
No.2编译期:将源代码编成机器码,每个模块生成obj文件,
No.3链接器:将n个obj文件组合在一起,解析他们之间的交叉关系,得到可执行文件。
平时我们所说的执行效率,是指可执行文件处理一组数据的效率,可能还听说过在程序设计比赛中可以利用预处理来做一些事情,以此减少程序处理数据的时间,那么同样,有些事情是可以在编译期做的,同样可以通过把一些事情提前到编译期来提高程序的效率。
首先要明白哪些工作可以在编译期做:
No.1当有函数重载时,编译器在编译期决定调用哪个函数;
No.2sizeof操作符,typedef操作符,+ - = < > :?等运算符,等等等
No.3enum类型的赋值
No.4模版的特化、偏特化和实例化
那么,可以在编译期做哪些事呢?
我总结的有两点:
1)计算一些数据
2)生成代码
计算数据时,比如,可以这样计算Fibonacci数列:
template<int N> struct Fibonacci { enum { result = Fibonacci<N-1>::result+Fibonacci<N-2>::result }; }; template<> struct Fibonacci<1> { enum { result =1 }; }; template<> struct Fibonacci<0> { enum { result =0 }; }; int main() { time_t t1=time(NULL); printf("%d\n",Fibonacci<40>::result); time_t t2=time(NULL); printf("UseTime:%d\n",t2-t1); return 1; };首先定义了一个模版,还有它的两个特化(针对1和0),接着调用Fiboncaai<40>::result,则编译器在编译时会尝试给模版中enum::result赋值,赋的是它后面那个表达式,而后面的表达式是一个另外两个模版的实例化,这同样也发生在编译期,所以编译器会继续跟下去,一直跟到Fiboncaai<1>::result+Fiboncaai<0>,然后编译器发现针对1和0是有模版特化的,于是它去调用特化,特化中定义了出口,于是赋值结束。可以将其理解为类递归,但不同的是,真正意义的递归是函数的嵌套调用本身,时间复杂度很高,而这里,由于在编译器,每次“递归”实质上是模版的实例化,而出口是模版的特化,所以不存在任何的函数嵌套调用。
上面Fiboncaai<40>输出的结果是102334155,反汇编看一下,如图:
编译器经过计算,直接在这里放了一个立即数,译成十进制正是102334155。
而上面代码中所消耗的时间是0。如图
而经过测试,用普通的函数递归计算Fiboncaai的第40个,需要8秒的时间。
用于生成代码时,也可以成为模版的元编程,元编程是指某类计算机程序的编写,这类计算机程序编写或者操纵其他程序(或者自身)作为它们的数据,或者在编译时完成部分本应在运行时完成的工作。很多情况下比手工编写全部代码相比工作效率更高。编写元程序的语言称之为元语言,被操作的语言称之为目标语言。一门语言同时也是自身的元语言的能力称之为反射。
由上面的定义可知,元编程也是工作在编译期,其实上面的计算数据的应用,也可以归为元编程,因为编译器不断的实例化模版来“递归”,本质上也是在帮我们生成代码。Loki库中的Typelist就是使用模版元编程的经典之作。
XX的封装和适配器模式以后再说吧
相关文章推荐
- c++模版的一些使用方法(一)
- c++模版的一些使用方法(四)
- c++模版的一些使用方法(二)
- 【C++】模版的概念、使用方法和深入了解
- C++一些库函数的使用方法
- C++ template的一些高级用法(元编码,可变参数,仿函数,using使用方法,. C++ 智能指针)
- 【C++】模版的概念、使用方法和深入了解
- 获取iframe中的内容、查找获取指定元素(关于用c++调用WEBBROWSER控件,使用相关接口操作web页面元素的一些方法)
- C++ template的一些高级用法(元编码,可变参数,仿函数,using使用方法,. C++ 智能指针)
- c++ 模版的使用方法
- 在.NET中使用类似于C++的template的方式定义一些通用方法
- C++:do...while(0)另类使用方法
- 在JAVA中, 在使用String.split方法时要注意的一些特殊分隔字符串
- 关于flash使用的一些方法
- opencv学习笔记:一些函数、类的使用方法
- c++ map的使用方法[转]
- 南大软院大神养成计划——关于DreamweaverCS6的一些基本使用方法
- Django中admin注册的方法以及一些常用使用技巧
- 进程类使用的一些方法及原理
- 浅谈Android Fragment嵌套使用存在的一些BUG以及解决方法