如果在C++有让一个变量存储任意类型,人们自然而然会想到void:
但是,void并没有很好地完成这项任务。我们看一下下面一段代码:
代码的目的很明显,A被当做万能数组来存放任意类型,但是,void的局限性也显现了出来。第一,我们没有办法将一个常量放入数组A,会产生编译错误;第二,我们在取出数组的元素时,我们需要对元素类型进行判断,如果一个人不小心,把1处写成int i2 = *(int *)A[2];,那么,后果需不堪设想,这就是典型的类型安全错误。
那么,我们如何既能保证类型安全,又能使用“万能容器”呢?这个任务由Boost::Any来完成。
我们首先来看一下使用Boost::Any的例子。
如果我们不小心把2处写成char * s = boost::any_cast<char *>(A[1]),由于boost::any_cast在类型转换时进行了类型检查,这时s将被赋为NULL。如果是值类型(非指针类型,如3 处),若类型检查没通过的话,将会抛出bad_any_cast异常。同时,我们可以很容易地将常量类型赋值给boost::any。注意,1处展示了 boost::any的一个缺点,它不能用来存放数组,这是由编译器无法在编译期动态分配内存的原因。
我们看一下boost::any代码的一些片断:
上面是boost::any的实现,为了方便讲述,我只保留了一些重要的实现,以后也将如此。我们可以看到,boost::any有一个类型为 placeholder的成员content,用来指向存储容器holder。holder派生自placeholder,是一个模板类。用基类指针指向模板子类,这样,any在实例化时就可以不用管存储的类型是什么,而直接把这项工作交给了编译器(注意赋值运算符等操作是模板函数),这就是 boost::any。
我们看一下boost::any_cast()的实现:
在实现中我们看到,boost::any_cast()通过使用typeid()来进行类型检查,如果类型不匹配,则返回0(即NULL)。这是boost::any_cast()对指针的特化版本。泛化版本如下:
泛化版本的boost::any_cast()使用了指针特化版本的boost::any_cast()。在类型不匹配的情况下,抛出bad_any_cast异常。
posted on 2009-05-12 19:45 Benjamin Luo 阅读(346) 评论(0) 编辑 收藏 引用 所属分类: 深入C++
Powered by: C++博客 Copyright © Benjamin Luo