刘未鹏|C++的罗浮宫

Knowledge sharing is the best reuse

刘未鹏ID:pongba
888555次访问,排名36好友14人,关注者173
兴趣:人工智能、机器学习、知识发现,认知科学。
pongba的文章
原创 101 篇
翻译 8 篇
转载 0 篇
评论 1734 篇
刘未鹏的公告
除非特别声明,本站采用Creative Commons License许可。转载请保留作者、出处。非商业。

FeedSkyFeedBurner
或者用 鲜果 GR 抓虾 订阅。

CSDN Blog暂时不支持RSS全文输出,对此感到不便的朋友可以使用强大的greasemonkey脚本:GReader Preview Enhanced(链接),该脚本支持在GReader里面直接打开全文页面。

P.S. 我经常出没于TopLanguage讨论组

《C++的罗浮宫》5年选集(下载)

——知识分享是最大的复用


讨论问题请到TopLanguage小组

TopLanguage


gtalk/msn(邮件请发送到gmail邮箱)

pongba@gmail.com
pp_liu@msn.com

豆瓣 饭否 美味书签

搜索C++的罗浮宫上的内容(不要回车,点击Go)

twitters

books I've translated




这个Blog上都写了哪些东东

最近评论
chenjing24:可以!
xingranliuyun:原来这里还有一份,在这里发些少于一百字的回复吧。

关于争吵。其实吵也就吵了,无所谓的,不吵架也是很奇怪的。

那个关于chrome的文章里提到了'm'键的使用。其实m键的功能对我来说有些无所谓,因为我一直都用浏览器看的,就算看到不感兴趣的主题,也不会认为是被打扰了。

因为以前一直看pongba的blog,有一天看到toplang……
Googol:爬过来又看了一遍,顺手把提到的基本书加到豆瓣的想读里。

ps 我不认为“存在即合理”是同义反复。当然这句话本身是高度概括的,甚至是抽象空洞的,因为没有表述请是什么情况下的存在和什么情况下的合理,每个人都可以把自己的理解往里面套。但存在和合理肯定是两个不同的概念,存在是一个物理上的属性,而合理则是逻辑上的。
zwp:这只是一个感想。
nirvash:一心称念弥陀圣号!
文章分类
收藏
相册
其它图片
文章中的图片
我的大头贴
C++
Andrei Alexandrescu
Andrew Lumsdaine
Bjarne Stroustrup
boost
C++ Standard Commitee
Doug Gregor
Hans J. Boehm
Jaakko Jarvi
Jeremy G. Siek
Matthew Wilson
newsgroups
boost.Developer
boost.User
comp.lang.c++.moderated
comp.std.c++
TopLanguage
Open Source
codeplex
Google AJAX Search API
Google Code Prettify
Google Web Toolkit
MS shared source initiative
notepad++
STLSoft
不认识的朋友们
fatalerror99
Glacier
realazy
SpiritEpic
TK
Yelz
YongSun
余晟|乱象&乱想
刘慈欣
吴欣安(atppp)
姬十三
张志强|阅微堂
许式伟
阮一峰
高远
鲍志云
其它
科学松鼠会
科学美国人
科幻世界
认识的朋友们
alai
chenyufei
dd
duguguiyu|Venus神庙
Googol
Joyfire
littlestone
lxwde
Matrix67
realfun
soloist
Tinyfool
windstorm
云风
冯大辉(Fenng)
刘新宇
刘江@图灵
史晓明
周星星
周筠@博文视点
孟岩
张振
徐宥|4G Spaces&Web 2.3
方舟@博文视点
李笑来|Pure Pleasure
杨文博
王信文|地球没有好朋友
荣耀
莫华枫
袁泳(g9)|负暄琐话
谢东升
陈冀康@华章
存档
订阅我的博客
XML聚合  FeedSky
订阅到鲜果
订阅到Google
订阅到抓虾
订阅到BlogLines
订阅到Yahoo
订阅到GouGou
订阅到飞鸽
订阅到Rojo
订阅到newsgator
订阅到netvibes

原创 boost源码剖析之:泛型指针类any之海纳百川(rev#2)收藏

新一篇: .NET Generics vs. C++ Templates | 旧一篇: 在C++中侦测内嵌型别的存在(rev#2)

boost源码剖析之:泛型指针类any之海纳百川(rev#2)

 

刘未鹏

C++的罗浮宫(http://blog.csdn.net/pongba)

 

动机

C++是强类型语言,所有强类型语言对类型的要求都是苛刻的,类型一有不合编译器就会抱怨说不能将某某类型转换为某某类型,当然如果在类型之间提供了转换操作符或是标准所允许的一定程度的隐式转换(如经过非explicit构造函数创建临时变量的隐式转换或是在intlong这些基本类型间的)又另当别论。总的说来,为了保持类型安全,C++有严厉的要求。然而有时候程序员可能有这样的需要:

 

int i;

iong j;

X x; // 假设X为用户定义的类

 

any anyVal=i;

... //use anyVal as a int value

 

anyVal=j;

... //use anyVal as a long value

 

anyVal=x;

... //use anyVal as a long value

 

考虑这样的一个泛型指针类该如何设计是很有趣的事情。

 

1. 它本身不能是模板类,因为如果它是模板,你必须为它的具现化提供模板参数。而事实上你并不想这样做。你想同一个对象接受任意类型的数据。在上面的代码中这个对象是anyVal。然而,如果你必须为它提供模板参数,那么上面的代码看起来就会像这样:

 

any<int> anyIntVal=i;

any<long> anyLongVal=j;

...

 

这显然已经丧失了anyVal的优势——以单个对象接受所有类型的数据。与其这样还不如直接写:

 

int anyIntVal=i;

int anyLongVal=j;

 

所以,any不能是模板类。

 

2. 它必须提供某些有关它所保存的对象类型的信息。

 

3. 它必须提供某种方法将它保存的数值取出来

 

事实上,boost库已经提供了这样的类boost::any,下面我就为你讲述它的原理及构造。

 

boost::any原理与结构

首先,any类里面一定要提供一个模板构造函数和模板operator=操作符。因为你必须允许用户写出:

 

any any_value(val); //val 的类型为任意的

any_value=val1; //val1 类型也是任意的

 

这样的代码。

 

其次,数据的存放之所是个问题,显然你不能将它保存在any类中,那会导致any类成为模板类,后者是明确不被允许的。数据应该动态存放,即动态分配一个数据的容器来存放数据,而any类中则保存指向这个容器的指针,明确地说,是指向这个容器的基类的指针,这是因为容器本身必须为模板,而any类中的指针成员又必须不是泛型的(因为any不能是泛型的,所以any中所有数据成员都不能是泛型的),所以,结论是:为容器准备一个非泛型的基类,而让指针指向该基类

 

下面就看一看boost库是如何具体实现这两点的。

 

摘自”boost/any.hpp”

 

class any

{

public:

 

class placeholder // 泛型数据容器holder的非泛型基类  

{                   

public:

// 虚析构函数,为保证派生类对象能用基类指针析构

virtual ~placeholder(){}

 

public:

  // 提供关于类型的信息

virtual const std::type_info & type() const = 0;

virtual placeholder * clone() const = 0;  // 复制

}; // placeholder

 

template<typename ValueType>

class holder : public placeholder

{

public:

holder(const ValueType & value)

: held(value)

{}

public:

virtual const std::type_info & type() const

{

  // typeid返回std::typeinfo对象引用,后者包含任意对象的类型信息, name,此外还提供operator==操作符你可以用typeid(oneObj)==typeid(anotherObj)来比两个对象之类型是否一致。

return typeid(ValueType); 

}

 

virtual placeholder * clone() const

{

return new holder(held);  // 改写虚函数,返回自身的复制体

}

 

public:

ValueType held; // 数据保存的地方

}; // holder

 

// 指向泛型数据容器holder的基类placeholder的指针

placeholder * content;

 

//模板构造函数,动态分配数据容器并调用其构造函数

template<typename ValueType>

any(const ValueType & value)

: content(new holder<ValueType>(value))

{}

...

// 与模板构造函数一样,但使用了swap惯用手法

template<typename ValueType>

any & operator=(const ValueType & rhs)

{

// 先创建一个临时对象any(rhs),再调用下面的swap函数进行底层数据交换,注意与*this交换数据的是临时对象,所以rhs的底层数据并未被更改,只是在swap结束后临时对象拥有了*this的底层数据,而此时*this也拥有了临时对象构造时所拥有的rhs的数据的副本。然后临时对象由于生命期的结束而被自动析构,*this