1.问题 在很多用C++开发服务器产品时,需要将不同的数据类型存储到一个容器中(有点类似HttpSession可以保存会话期间任意类型的数据),供其它使用程序查找。 在Java和C#中这是一个简单的问题,可以使用Object对象来实现类型无关的数据结构,并且很好的解决了内存回收等问题。 但C++中很难做到这一点,C++是一门静态类型语言,没有一个所有类型的基类。
2.一般方法 一般解决这个问题的办法是使用void*指针来存储数据,象下面的代码: map<string,void*> 但是这样带来几个问题: (1)因为C++在不知道类类型时无法正确的释放内存; (2)很多使用者使用它时,释放内存的时机难于确定;
3.让它正确释放内存 我们可以定义一个公共的基类,让所有需要放到容器的类型继承它 class Object { public: virtual ~Object(){cout<<"Object Destroy" << endl;} }; 由于使用了virtual析构函数因此可以确保delete obj的时可以正常工作。因此上面的容器定义变成了这样: map<string,Object*>
4.让它知道何时释放内存 大家都知道,这时必须使用引用计数,不过很幸运有现成的,我们使用boost::share_ptr map<string,boost::share_ptr<Object*> > 很好两个问题都已经解决,但如何向他们中加入C++的基本类型呢?
5.开发基本类型的封装类 基本类型很多,如果每一个都写一个类,太累了,我们可以定义一个模板,这里的难点是基本类型之间的操作符重载,不同类型之间的运算返回的类型并不相同,这就需要写很多重载函数,在这里我们使用Loki来简化这些操作。使用Loki的TypeList来自动计算应该是什么返回值 #include"Typelist.h" //Loki头文件 template <typename T> class PrimerType:public Object { public: typedef T value_type;//基本类型 typedef PrimerType<T> class_type;//基本类型的对象类型 public: PrimerType() :m_value((value_type)0) { } template<typename Other> PrimerType(const Other& value) :m_value(value) { } ~PrimerType() { cout<<"PrimerType Destroy" << endl; } //基本类型转换操作符重载 operator value_type() const { return m_value; } //赋值操作符重载 const class_type& operator=(value_type value) { m_value=value; return *this; } bool operator!( ) const { return !m_value; } //作为类成员的算术运算符操作符重载 class_type& operator++() {// ++ 前缀 m_value+=1; return *this; } const class_type operator++(int) {// ++ 后缀 class_type oldValue=*this; m_value+=1; return oldValue; } class_type& operator--() {// -- 前缀 m_value-=1; return *this; } const class_type operator--(int) {// -- 后缀 class_type oldValue=*this; m_value-=1; return oldValue; } class_type& operator+=(const value_type& value) { m_value+=value; return *this; } //。。。省略-= /= *= &= |= ^= %= 等等 private: value_type m_value; friend istream& operator>><T> ( istream& is, class_type& ptvalue ); }; //流输入函数,不用输出(通过类型操作符重载自动完成) template<typename T> istream& operator>> ( istream& is, PrimerType<T>& ptvalue ) { is >> ptvalue.m_value; return is; } //基本类型重定义 typedef __int8 int8; typedef __int16 int16; typedef __int32 int32; typedef __int64 int64; typedef unsigned __int8 uint8; typedef unsigned __int16 uint16; typedef unsigned __int32 uint32; typedef unsigned __int64 uint64; //基本类型的对象类型 typedef PrimerType<bool> Boolean; typedef PrimerType<int8> Int8; typedef PrimerType<int16> Int16; typedef PrimerType<int32> Int32; typedef PrimerType<int64> Int64; typedef PrimerType<uint8> UInt8; typedef PrimerType<uint16> UInt16; typedef PrimerType<uint32> UInt32; typedef PrimerType<uint64> UInt64; typedef PrimerType<float> Float; typedef PrimerType<double> Double; typedef PrimerType<long> Long; typedef PrimerType<unsigned long> ULong; //更友好的名字 typedef Int8 Char; typedef Int16 Short; typedef Int32 Int; typedef UInt8 Byte; typedef UInt16 UShort; typedef UInt32 UInt; //算术运算返回类型的traits,运算时以排在后面的类型返回 #define PRIMERTYPELIST TYPELIST_13(bool,int8,uint8,int16,uint16,int32,uint32,long,unsigned long,int64,uint64,float,double) // | // int template <typename T1, typename T2> struct ResultType_Traits { enum { lefttype_index =::Loki::TL::IndexOf<PRIMERTYPELIST,T1>::value}; enum { righttype_index =::Loki::TL::IndexOf<PRIMERTYPELIST,T2>::value}; enum { resulttype_index = (lefttype_index>righttype_index)?lefttype_index:righttype_index}; //在vc7.1下int32以前的类型做算术运算都返回int32类型 typedef typename ::Loki::TL::TypeAt<PRIMERTYPELIST, (resulttype_index<5)?5:resulttype_index >::Result result_type; }; //作为全局的算术运算符操作符重载 + - * / template<typename T1,typename T2> typename ResultType_Traits<T1,T2>::result_type operator +(const PrimerType<T1>& lhs,const T2& rhs) { return (T1)lhs+rhs; } template<typename T1,typename T2> typename ResultType_Traits<T1,T2>::result_type operator +(const T1& lhs,const PrimerType<T2>& rhs) { return lhs+(T2)rhs; } template<typename T1,typename T2> typename ResultType_Traits<T1,T2>::result_type operator +(const PrimerType<T1>& lhs,const PrimerType<T2>& rhs) { return (T1)lhs+(T2)rhs; } //。。。省略 - * /等等 // 逻辑运算符重载 template<typename T1,typename T2> bool operator ==(const PrimerType<T1>& lhs,const T2& rhs) { return (T1)lhs==rhs; } template<typename T1,typename T2> bool operator ==(const T1& lhs,const PrimerType<T2>& rhs) { return lhs==(T2)rhs; } template<typename T1,typename T2> bool operator ==(const PrimerType<T1>& lhs,const PrimerType<T2>& rhs) { return (T1)lhs==(T2)rhs; } //。。。省略 != >= 等等 6.小结 使用对象来表示基本类型,由于使用了virtual的析构它是有内存浪费的,但在很多应用中它是很有用的。 同时你可以增加String/DateTime的特化支持,这样就完整了 如有不足欢迎指点
环境:window2000+vc7.1 
|