boost::any用法示例:

#include <iostream>
#include <list>
#include <boost/any.hpp> typedef std::list<boost::any> list_any; //关键部分:可以存放任意类型的对象
void fill_list(list_any& la)
{
la.push_back();//存放常数
la.push_back( std::string("dyunze") );//存放字符串对象;注意la.push_back(“dyunze”)错误,因为会被当错字符串数组
} //根据类型进行显示
void show_list(list_any& la)
{
list_any::iterator it;
boost::any anyone; for( it = la.begin(); it != la.end(); it++ )
{
anyone = *it; if( anyone.type() == typeid(int) )
std::cout<<boost::any_cast<int>(*it)<<std::endl;
else if( anyone.type() == typeid(std::string) )
std::cout<<boost::any_cast<std::string>(*it).c_str()<<std::endl;
}
} int main()
{
list_any la;
fill_list(la);
show_list(la); return ;
}

boost::any的优点:

对设计模式理解的朋友都会知道合成模式。因为多态只有在使用指针或引用的情况下才能显现,所以std容器中只能存放指针或引用(但实际上只能存放指针,无法存放引用,这个好像是c++的不足吧)。如:

std::list<BaseClass*> mylist;

这样,我们就要对指针所指向内容的生存周期操心(可能需要程序员适时删除申请的内存;但是由于存放指针,插入/删除的效率高),而使用boost::any就可能避免这种情况,因为我们可以存放类型本身(当然存放指针也可以)。这是boost::any的优点之一。

boost::any另一个优点是可以存放任何类型。而前面提到的mylist只能存放BaseClass类指针以及其继承类的指针。

boost::any的缺点:

由于boost::any可以存放任何类型,自然它用不了多态特性,没有统一的接口,所以在获取容器中的元素时需要实现判别元素的真正类型,这增加了程序员的负担。与面向对象编程思想有些矛盾,但整个标准c++模板库何尝不是如此,用那些牛人的话来说,是“有益补充”。

总之,有利必有弊,没有十全十美的。

分析并模仿boost::any:

读了一下boost::any的源代码,并模仿一下其实现(相当一部分时拷贝原代码),下面是代码(只包含必要功能)。

实现any的功能主要由三部分组成:
1)any类
2)真正保存数据的holder类及其基类placeholder
3)获取真正数据的模板函数any_cast,类型转换的功能。

#include <iostream>
#include <list>
#include <cassert> //自定义的any类
class any
{
public: //保存真正数据的接口类
class placeholder
{
public:
virtual ~placeholder()
{
}
public: virtual const std::type_info & type() const = ;
virtual placeholder * clone() const = ;
}; //真正保存和获取数据的类。
template<typename ValueType>
class holder : public placeholder
{
public:
holder(const ValueType & value): held(value)
{
} public: virtual const std::type_info & type() const
{
return typeid(ValueType);
} virtual placeholder * clone() const
{
return new holder(held);//使用了原型模式
} public: //真正的数据,就保存在这里
ValueType held;
}; public: any(): content(NULL)
{
} //模板构造函数,参数可以是任意类型,真正的数据保存在content中
template<typename ValueType>
any(const ValueType & value): content(new holder<ValueType>(value))
{
} //拷贝构造函数
any(const any & other)
: content(other.content ? other.content->clone() : )
{
} //析构函数,删除保存数据的content对象
~any()
{
if(NULL != content)
delete content;
} private:
//一个placeholde对象指针,指向其子类folder的一个实现
// 即content( new holder<ValueType>(value) )语句
placeholder* content; template<typename ValueType> friend ValueType any_cast(const any& operand);
public: //查询真实数据的类型。
const std::type_info & type() const
{
return content ? content->type() : typeid(void);
}
}; //获取content->helder数据的方法。用来获取真正的数据
template<typename ValueType>
ValueType any_cast(const any& operand)
{
assert( operand.type() == typeid(ValueType) );
return static_cast<any::holder<ValueType> *>(operand.content)->held;
} //下代码是使用示例 typedef std::list<any> list_any; void fill_list(list_any& la)
{
la.push_back();//存放常数;调用了any的模板构造函数,下同
la.push_back( std::string("我是string") );//存放字符串对象;注意la.push_back(“dyunze”)错误,因为会被当错字符串数组 char* p = "我是常量区字符串abc";
la.push_back(p);//可以存放指针,但要注意指针的失效问题
} //根据类型进行显示
void show_list(list_any& la)
{
list_any::iterator it; for( it = la.begin(); it != la.end(); it++ )
{ if( (*it).type() == typeid(int) )
std::cout<<any_cast<int>(*it)<<std::endl;
else if( (*it).type() == typeid(std::string) )
std::cout<<any_cast<std::string>(*it).c_str()<<std::endl;
else if( (*it).type() == typeid(char*) )
std::cout<<any_cast<char*>(*it)<<std::endl;
}
} int main()
{
list_any la;
fill_list(la);
show_list(la); return ;
}

参考文献

1)http://www.nohack.cn/code/other/2006-10-05/10230.html

2)boost::any源代码

[转] boost::any的用法、优点和缺点以及源代码分析的更多相关文章

  1. boost::function的用法

    本片文章主要介绍boost::function的用法. boost::function 就是一个函数的包装器(function wrapper),用来定义函数对象. 1.  介绍 Boost.Func ...

  2. 转:RTMPDump源代码分析

    0: 主要函数调用分析 rtmpdump 是一个用来处理 RTMP 流媒体的开源工具包,支持 rtmp://, rtmpt://, rtmpe://, rtmpte://, and rtmps://. ...

  3. 转:ffdshow 源代码分析

    ffdshow神奇的功能:视频播放时显示运动矢量和QP FFDShow可以称得上是全能的解码.编码器.最初FFDShow只是mpeg视频解码器,不过现在他能做到的远不止于此.它能够解码的视频格式已经远 ...

  4. hostapd源代码分析(二):hostapd的工作机制

    [转]hostapd源代码分析(二):hostapd的工作机制 原文链接:http://blog.csdn.net/qq_21949217/article/details/46004433 在我的上一 ...

  5. Android应用程序绑定服务(bindService)的过程源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6745181 Android应用程序组件Serv ...

  6. Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6664554 在上一文章Android系统匿名共 ...

  7. JAVA随笔篇一(Timer源代码分析和scheduleAtFixedRate的使用)

    写完了基础篇,想了非常久要不要去写进阶篇.去写JSP等等的用法.最后决定先不去写.由于自己并非JAVA方面的大牛.眼下也在边做边学,所以决定先将自己不懂的拿出来学并记下来. Timer是Java自带的 ...

  8. ffdshow 源代码分析 2: 位图覆盖滤镜(对话框部分Dialog)

    ===================================================== ffdshow源代码分析系列文章列表: ffdshow 源代码分析 1: 整体结构 ffds ...

  9. Java集合系列之TreeMap源代码分析

    一.概述 TreeMap是基于红黑树实现的.因为TreeMap实现了java.util.sortMap接口,集合中的映射关系是具有一定顺序的,该映射依据其键的自然顺序进行排序或者依据创建映射时提供的C ...

随机推荐

  1. Python文件之----JSON

    #coding=utf-8import json def writeJSON(filaName="test.json"): f=open(filaName, "wb&qu ...

  2. 你好,C++(40)7.1 一切指针都是纸老虎:彻底理解指针

    第7章 C++世界的奇人异事 在武侠小说中,初入武林的毛头小子总是要遇到几位奇人,发生几件异事,经过高人的指点,经历一番磨炼,方能武功精进,从新手成长为高手.在C++世界,同样有诸多的奇人异事.在C+ ...

  3. 用core dump来调试程序段错误

    有的程序可以通过编译, 但在运行时会出现Segment fault(段错误). 这通常都是指针错误引起的.但这不像编译错误一样会提示到文件->行, 而是没有任何信息, 使得我们的调试变得困难起来 ...

  4. Unique Binary Search Tree

    Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...

  5. Mysql 数据类型使用说明

    FLOAT 和DOUBLE 类型支持使用标准的浮点运算进行近似计算. DECIMAL类型用于存储精确的小数. 因为cpu不支持对DECIMAL的直接计算,所以在Mysql5.0及更高的版本中,MYSQ ...

  6. HTML语义化标签(一)

    总所周知,现在的网页是由HTML.CSS.JS三大元素组成,而HTML是其中最重要的部分,是整个网页的骨架,CSS和js在骨架的基础上进行相应的修饰,使得网页成为一个有血有肉,可以动的“人”.如果HT ...

  7. 【行为型】Mediator模式

    中介者模式目的是将对象间的交互封装在一个对象中,从而使用各对象间的相互依赖解耦,并可以独立更改对像间的交互.在实际项目开发过程中,因某些原因(如:业务逻辑处理不当或设计不当等)使得多个不同对象间需要相 ...

  8. 嵌入式学习笔记(虚拟机共享文件夹配置-Ubuntu系统中)

    最近在学习Linux的操作系统,使用的是虚拟机.由于一些文件需要在主机和虚拟机中都要编辑,如果可以使得文件共享,可以极大的提高工作效率! 配置共享文件的步骤如下: [第一步] 在虚拟机软件中设置 [第 ...

  9. 快速排序(Quick Sort)的C语言实现

    快速排序(Quick Sort)的基本思想是通过一趟排序将待排记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对着两部分记录继续进行排序,以达到整个序列有序,具体步骤 ...

  10. IPv6套接字地址结构

    IPv6套接字地址结构 struct in6_addr{ unit8_t sa_addr[16]; }; #define SIN6_LEN struct sockaddr_in6{ unit8_t s ...