c++模板技术
来源:互联网 发布:佛山正大数据恢复中心 编辑:程序博客网 时间:2024/05/17 03:23
转自http://blog.csdn.net/ilovedrv/archive/2010/07/10/5725402.aspx
1 概述
c++的模板技术是把双刃剑,一方面,模板灵活强大,变换无穷,stl、boost给程序员展现了模板技术的匪夷所思;另一方面,模板又是c++中处理虚机制外最复杂的技术,初学者往往不知所云。本文简单的总结了以下自己工作中遇到的几个问题,希望能对读者有所帮助。
2 关键字 typename vs class
在模板定义时的class和typename是没有区别的,因为最初发明模板时决定使用class以减少一个关键字,但后来发现还是不得不加上typename关键字,参见如下代码:
- template<class C>
- void f(C & rc)
- {
- typename C::iterator i = rc.begin();
- // ...
- }
编译器不知道C的定义,所以不知道C::iterator是什么东西,此处必须有typename来告诉编译器,而不能使用class关键字。在Windows的vc6环境下,typename可以省略,编译器自动识别补全,但在Linux的gcc编译时,提示需要添加typename。
3 静态变量初始化
在Windows和Linux下移植C++代码,尤其是模板,十分头疼,Windows下的VC对C++标准支持的不是很好,而且还对很多C++标准进行了修改和扩展,这给移植增加了更大困难,另外gcc不同版本之间也有区别。
以下代码演示了多类型的静态变量初始化。
- template <typename T>
- class Image
- {
- public:
- static const int flag;
- // ...
- };
- const int Image<int>::flag = 10;
- const int Image<float>::flag = 15;
上面的代码,在vc6和gcc 3.2.2下均能编译通过,但在新版gcc4.2.3下出现编译器内部错误,需要采用如下方式初始化:
- template <> const int Image<int>::flag = 10;
- template <> const int Image<float>::flag = 15;
4 模板之多态
在c++中,实现类型多态有两种方式:虚函数和模板。 一般情况下,开发者习惯使用虚函数机制,这种方式采用的是动态绑定技术,即程序只有在运行时才能获得函数执行入口,所以需要由编译器自动生成一张虚函数表;而模板方式采用的是静态绑定,即在编译阶段就能获取函数入口,这种多态实现比较少见。参见如下示例:
- #include <iostream>
- using namespace std;
- template <typename T>
- class B1
- {
- public:
- void SayHi()
- {
- T* pT = static_cast<T*>(this);
- pT->PrintClassName();
- }
- void PrintClassName() { cout << "This is B1" << endl ; }
- };
- class D1 : public B1<D1>
- {
- // No overridden functions at all
- };
- class D2 : public B1<D2>
- {
- public:
- void PrintClassName() { cout << "This is D2" << endl ; }
- };
- int main()
- {
- D1 d1;
- D2 d2;
- d1.SayHi(); // prints "This is B1"
- d2.SayHi(); // prints "This is D2"
- return 0;
- }
class D1 : public B1<D1> 定义是合法的,因为c++语法支持,即D1只是被部分定义,类名D1已经被列入递归继承列表,是可以使用的。将类名作为模板类的参数实现了编译期间的虚函数调用机制。
上面static_cast<T*>(this)是关键所在,它根据函数调用时的特殊处理将指向B1类型的指针this指派为D1或D2类型的指针,因为模板代码是在编译其间生成的,所以只要编译器生成正确的继承列表,这样指派就是安全的。这很像C++的多态(polymorphism),只是SayHi()方法不是虚函数。
在第一个函数调用,对象B1被指派为D1,所以代码被解释成:
- void B1<D1>::SayHi()
- {
- D1* pT = static_cast<D1*>(this);
- pT->PrintClassName();
- }
D2实现类似。采用这种方法的优势:不需要虚函数表;静态绑定,有利于程序优化。
- 【C++】traits技术与模板元编程
- 模板技术
- C++_模板类与类型萃取技术
- STL(二)C++模板技术
- C++-模板
- C++-模板
- C++:模板
- C++:模板
- C++:模板
- 模板 (C++)
- C ++ 模板
- C ++ 模板
- 【C++】模板
- c++----------模板
- C++--------------------------------------------模板
- c++--模板
- C++:模板
- ASP模板技术
- Android应用程序显示欢迎画面并开机自启动
- Kinect for Windows SDK开发入门(五):景深数据处理 下
- 【Leetcode】Path Sum
- 实例阐述浮点数解包运算过程
- 深入理解 jdk 动态代理的实现
- c++模板技术
- 我的第一篇博文
- Cocos2D-x游戏开发之一:场景切换
- MFC (1)CAnimate Control 应用
- 我的第一周作业
- 链表,队列和栈的区别
- C#_为WinForm窗体定义功能快捷键
- 用Javascript获取页面元素的位置/JQUERY对尺寸的定义
- java进阶(2):集合类:ArrayList的遍历,节点的删除和插入