c++实现Any类

这篇博客参考c++任意类型Any类的实现,稍加改动。原博客中是使用泛型的占位变量Holder对象来保存数据,而Any不是模板类,Any类中构造函数是模板函数,以向Holder中存入不同类型的数据。Any类实现的主要是类型擦除这一操作,这里使用的是void*指针,认为任何一个数据无非是存储地址与解读方式的组合,void*指针可以保存指向任何类型数据的指针(即存储地址),剩下的再使用一个字符串类变量保存其类型(即数据的解读方式)。
该例中使用setData函数来将Any类的对象设定为某一个具体的数据,使用getData函数来解析Any中保存的数据,二者都是泛型函数:

class Any
{
public:
	Any() :pData(NULL), type("null") {}
	template<class ValueType>
	Any(const ValueType& value) { setData(value); }
	template<class ValueType>
	void setData(const ValueType& value) { pData = (void*)(&value); type = typeid(value).name(); }
	template<> void setData<Any>(const Any& value) { if (this != &value) { this->pData = value.pData; this->type = value.type; } }
	template<class ValueType>
	bool getData(ValueType& dst) { if (!isCompatible(dst))return false; dst = *(ValueType*)(pData); return true; }
	template<class ValueType>
	bool isCompatible(const ValueType& value) { return (string)(typeid(value).name()) == string(this->type); }
	void* getAddress() { return pData; }
	const char* getType() { return type; }
	bool isNull() { return pData == NULL; }
	template<class ValueType>
	Any& operator=(const ValueType& value) { this->setData(value); return *this; }
	template<class ValueType>
	operator ValueType() { return *(ValueType*)(pData); }
	template<class ValueType>
	void display() { string t = (string)type; cout << "地址为:" << this << "的Any对象指向地址为:" << this->pData << "的" << this->type << "类型的数据:" << *(ValueType*)(pData) << endl; }
private:
	void* pData;
	const char* type;
};

其中构造函数Any(const ValueType& value)以及=运算符重载无非是调用了setData,只是提供一种便利的使用方式;包括operator ValueType()也是提供一种便利的Any类型向其他类型转换的方式;Any的display()函数只是用于测试。其测试如下:

class Test
{
public:
	int h = 4;
	void display() { cout << "Test对象地址:" << this << ",h=" << h << endl; }
};

int main()
{
	Any any, any1;
	int a = 7, a1;
	float b = 4.1, b1;
	double c = 0.315, c1; 
	string s1 = "Hello", s2;
	Test t, t1;
	t.h = 5;
	t1.h = 15;
	any = a;
	any.display<int>();
	a1 = any;
	cout << "a1=" << a1 << endl;
	any = b;
	any.display<float>();
	b1 = any;
	cout << "b1=" << b1 << endl;
	any = c;
	any.display<double>();
	c1 = any;
	cout << "c1=" << c1 << endl;
	any = s1;
	any.display<string>();
	any.getData(s2);
	//s2 = any;
	cout << "s2=" << s2 << endl;
	t.display();
	any = t;
	t1.display();
	t1 = any;
	t1.display();
	any1 = any;
	system("pause");
    return 0;
}

可以看到Any类可以赋值为intfloatdouble等基本类型以及string和自定义的Test类型,有点美中不足的是Any对象如果保存string类型不能直接通过=运算符赋值给string类型变量,会出现“operatr=”不明确错误。这个我目前不知什么原因。以下是测试结果:
在这里插入图片描述
建议的使用方法是:

  • 给Any对象赋值:直接使用=运算符,如any=b
  • 把Any对象赋值给其他变量:想调用isCompatible函数判断类型是否一样,然后使用getData函数;对于一些基本类型的intfloatdouble可以直接用=运算符将Any对象赋值给其他类型,但是=运算符方式不检查类型。

本例中方法更类似于这篇博客Any类的实现

另外Any类在boost库中有定义,可以使用现成的轮子。

发布了28 篇原创文章 · 获赞 14 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/liyunxin_c_language/article/details/98325080