4.6.1 万能类型boost::any
《把脉VC++》第4章对象的赋值与转换,本章介绍了对象的初始化(从无到有)和赋值(从A到B)问题,讨论如何对对象进行类型上的、数值上的转换,并结合我们常常接触到的数学运算和字符编码问题展开讨论。本节讲述的是万能类型boost::any。
AD:
4.6 使用第三方库
以上介绍了Visual C++对对象赋值、转换及字符编码转换的方法,实际上还有一些好用的第三方类库用以辅助C++程序员完成对象处理,比较著名的就是boost。本节简单介绍boost库中与数值相关的boost::any、boost::lexical_cast,以及有理数类boost::rational。
4.6.1 万能类型boost::any
boost库提供了any类,boost::any是一个能保存任意类型值的类,这一点有点像variant类型,不过variant由于采用了一个巨大的union,效率非常低。而boost利用模板,保存的时候并不改变值的类型,只是在需要的时候才提供方法让用户进行类型判断及取值。
boost::any几乎可以用来存储任何数据类型:
- boost::any ai, as;
- ai = 100;
- as = string("hello");
需要的时候,我们又可以使用any_cast将原来的数据还原:
- int i = boost::any_cast<int>(ai);
- string s = boost::any_cast<string>(as);
当这种转换发生类型不匹配时,会有异常bad_any_cast发生:
- try
- {
- int i = boost::any_cast<int>(as);
- }
- catch(boost::bad_any_cast & e)
- {
- }
在传统的C++程序中,为了支持各种数据类型,我们不得不使用万能指针"void *",但是很遗憾的是,基于万能指针的转换是不安全的,"void*"缺少类型检查。所以,我们建议大家尽量使用any类。
现在动手
编写如下程序,体验如何使用boost::any来完成对象类型转换。
【程序 4-10】使用boost::any完成对象类型转换
- 01 #include "stdafx.h"
- 02 #include "boost/any.hpp"
- 03 #include <string>
- 04
- 05 using namespace std;
- 06 using namespace boost;
- 07
- 08 class Cat
- 09 {
- 10 };
- 11
- 12 void print(any it)
- 13 {
- 14 if(it.empty())
- 15 {
- 16 printf("nothing!\r\n");
- 17 return;
- 18 }
- 19
- 20 if(it.type() == typeid(int))
- 21 {
- 22 printf("integer: %d\r\n", any_cast<int>(it));
- 23 return;
- 24 }
- 25
- 26 if(it.type() == typeid(string))
- 27 {
- 28 printf("string: %s\r\n", any_cast<string>(it).c_str());
- 29 return;
- 30 }
- 31
- 32 if(it.type() == typeid(CString))
- 33 {
- 34 _tprintf(_T("CString: %s\r\n"), any_cast<CString>(it));
- 35 return;
- 36 }
- 37
- 38 if(it.type() == typeid(Cat))
- 39 {
- 40 _tprintf(_T("oops! a cat!\r\n"));
- 41 return;
- 42 }
- 43 }
- 44
- 45 int main()
- 46 {
- 47 print(100);
- 48
- 49 any as[] = {any(), 100, string("hello"), CString("world"), Cat()};
- 50 for(int i = 0; i < sizeof(as) / sizeof(as[0]); i++)
- 51 {
- 52 print(as[i]);
- 53 }
- 54
- 55 return 0;56 }
结果输出如图4-18所示。
目对应于光盘中的目录"\ch04\BoostAnyTest"。