首先说一下什么Any类呢?
从英文名可以看出就是任何的意思,一般对象都是各个类型的,通过这个Any可以让各个对象的类型全部擦除,也就是将一个对象的类型先消除,等到用到 的时候再将对应的类型赋值。
boost库中也又Any类,先不说这个,想要的可以自行百度。
以下是一个简单的例子
#include <boost/any.hpp>
#include <vector>
boost::any s= "test";
boost::any b = 2.5;
std::vector<boost::any> v;
v.push_back(s);
v.push_back(b);
int va = boost::any_cast<string>(s);
int vb = boost::any_cast<double>(b);
关键点:
any能够容纳所有类型的数据,当赋值给any的时候需要将值的类型擦除,以通用的方式保存所有类型的数据。
如何能够将擦除的类型保存起来呢?
可以通过继承擦除类型,基类是不包含模板参数的,派生类中才有模板参数,这个模板参数正是赋值的类型。
赋值时,将创建的派生类对象赋值给基类指针。
基类的派生来携带了数据类型,基类只是原始数据的一个占位符,通过多态的隐式转换擦除了原始数据的类型。
因此,任何数据类型都能赋值给它,从而能实现存放所有的类型。
如何转换成原始类型呢?
取数据的时候需要向下转换成派生类来获取原始数据,当转换失败时,打印详情,抛出异常。
给Any赋值的时候,还要管理该对象的生命周期,所以用只能指针来管理。
struct Base;
typedef std::unique_ptr<Base> BasePtr;//智能指针管理对象的生命周期。
struct Base
{
virtual ~Base() {}
virtual BasePtr Clone() const = 0;
};
template<typename T>//赋值的相关类型
struct Derived : Base
{
template<typename U>
Derived(U && value) : m_value(std::forward<U>(value)) { }
BasePtr Clone() const
{//赋值时,将创建的派生类对象赋值给基类指针。
return BasePtr(new Derived<T>(m_value));
}
T m_value;
};
BasePtr Clone() const
{
if (m_ptr != nullptr)
return m_ptr->Clone();
return nullptr;
}
BasePtr m_ptr;
std::type_index m_tpIndex;
接下来看看实际调用的例子:
void TestAny()
{
string s1 = "hello";
Any any2;
any2 = s1;
string s2 = any2.AnyCast<string>();//转换正确,将值赋值给s2,失败抛出异常。
cout << "s2 = " << s2 << endl;
bool ret1 = any2.IsNull();//转换以后为0,为转换之前为1
bool r = any2.Is<string> //看是否转成对应的类型。
cout << "testany()" << "ret1 = " << ret1 << "r = " << r << endl;
}
在c++中,typeid用于返回指针或引用所指对象的实际类型。