如何用C++ union 来 实现一个 C# object
2012-03-15 18:51
453 查看
C#的 object 相信用过的人都能体会出它的优点, 可以 实现 任意类型的boxed,unboxed , 如下 int n = 10; object o = n; int m = (int) o; 在类型的传递中可以起到一个自适配的容器, 这种写法 在接口的统一 上 能起到很好的作用 , 比如你不知道如何传递一个未知类型的参数时 , 你可以在接口处定义 object 参数让 真正接口的实现者自己去抉择。 说到这 可能有不少惯用 C 的人会说 这不就是一个变向的 void* 么,
恩这话说对了一半,但 void * 的不安全性在于 当使用者 用错类型的时候可能会出现访问越界 。 但 object因为本身的 沙盒 特性避免了一部分外部对它内部空间的越界操作。 在 C++ 的世界里也有 一个 void* 的替代品 ,那就是 union 。 union 理论上可以实现所有类型的容器 ,虽然得面对个问题 : union 也需要你使用者知道传递的类型而且 还必须 保证知道 union 内部的构造, 比如 union UData { unsinged int nU32; } 当用到UData
ud 给 外部赋值的时候 就得用 unsinged int n = ud.nU32; 这种显式的方式把 nU32这种内部结构暴露给使用者。 有什么方法能保证 外部使用的时候不关心这点呢 ,其实外部 变量 n 已经提供给编译器 自己的变量 类型 unsinged int 了, 如果编译器自己 知道 该从 union上取到 nU32这种东西就好了 。。。。 答案是否定的, 编译器怎么会知道你 union里面还包含了个 nU32 , 当你想写出 n = ud ; 这种 自然的 等式 时 ,编辑器该上哪去找
nU32? 等等 貌似 有这种问题的解决 方式 ,就是 operator 符号 ,但这种符号常常在 class , struct 里出现 ,但 union 能不能支持 ? 带这种疑问试验了 如下的写法 :
luck ,编辑器认识,并且正确的把 1 付给了 n ; 问题看上去解决了, 但是 _d.nU32 似乎还是让外部看见了。 恩, 万能的 operator 貌似也能解决这个问题
好了,ok 。但似乎还是有不舒服的地方, 一个 union 定义写这么大块,不太容易看于是 最终懒汉方案产生
值得注意的是要防止typedef过的类型在注册的时候重定义,比如 typedef 了一个 int 的 PID ,那么 PID nID在 UData 中就不能使用 _UNION_CONVER 这个宏了,但是可以如下的方式定义, 同样不影响 nID的赋值和取值
恩这话说对了一半,但 void * 的不安全性在于 当使用者 用错类型的时候可能会出现访问越界 。 但 object因为本身的 沙盒 特性避免了一部分外部对它内部空间的越界操作。 在 C++ 的世界里也有 一个 void* 的替代品 ,那就是 union 。 union 理论上可以实现所有类型的容器 ,虽然得面对个问题 : union 也需要你使用者知道传递的类型而且 还必须 保证知道 union 内部的构造, 比如 union UData { unsinged int nU32; } 当用到UData
ud 给 外部赋值的时候 就得用 unsinged int n = ud.nU32; 这种显式的方式把 nU32这种内部结构暴露给使用者。 有什么方法能保证 外部使用的时候不关心这点呢 ,其实外部 变量 n 已经提供给编译器 自己的变量 类型 unsinged int 了, 如果编译器自己 知道 该从 union上取到 nU32这种东西就好了 。。。。 答案是否定的, 编译器怎么会知道你 union里面还包含了个 nU32 , 当你想写出 n = ud ; 这种 自然的 等式 时 ,编辑器该上哪去找
nU32? 等等 貌似 有这种问题的解决 方式 ,就是 operator 符号 ,但这种符号常常在 class , struct 里出现 ,但 union 能不能支持 ? 带这种疑问试验了 如下的写法 :
union UData { unsinged int nU32; operator unsigned int() { return nU32; } }; unsigned int _n; UData _d; _d.nU32 = 1; _n = _d;
luck ,编辑器认识,并且正确的把 1 付给了 n ; 问题看上去解决了, 但是 _d.nU32 似乎还是让外部看见了。 恩, 万能的 operator 貌似也能解决这个问题
union UData { unsinged int nU32; void operator (const unsigned int& right) { nU32 = right;}; operator unsigned int() { return nU32; } }; unsigned int _n; UData _d; _d = 1; _n = _d;
好了,ok 。但似乎还是有不舒服的地方, 一个 union 定义写这么大块,不太容易看于是 最终懒汉方案产生
#define _UNION_CONVER(type,var) type var; \ void operator=( const type& _right) { var = _right;};\ operator type{ return var;} union UData { _UNION_CONVER(unsigned int , nU32); _UNION_CONVER( int , n32); _UNION_CONVER( bool , bBool); _UNION_CONVER( float , fFloat); }; UData _d; _d = 1; unsinged int _n = _d; _d = -1; int _m = _d; _d = false; bool _b = _d; _d = 0.02f; float _f = _d;
值得注意的是要防止typedef过的类型在注册的时候重定义,比如 typedef 了一个 int 的 PID ,那么 PID nID在 UData 中就不能使用 _UNION_CONVER 这个宏了,但是可以如下的方式定义, 同样不影响 nID的赋值和取值
union UData { _UNION_CONVER(unsigned int , nU32); _UNION_CONVER( int , n32); _UNION_CONVER( bool , bBool); _UNION_CONVER( float , fFloat); PID nID: };好吧得承认面对新类型时还得在添加一句 _UNION_CONVER 这种做法还是没有C# object 用着爽,但毕竟那是 keyword, 编译器支持的, 如果C++ 编译器在编译新的类型时也能如 template一样自动填写一个变量类型就完美了。 顺带一提 g++编辑器也能支持 这种 union 里面的 嵌operator 写法
相关文章推荐
- 面试例题:输入n,求一个n x n矩阵,规定矩阵沿45度递增,形成一个zigzag数组(JPEG编码里取像素数据的排列顺序),请问如何用C++实现? (中国台湾著名硬件公司2007年11月面试题)
- C/C++系列之如何实现一个avi格式的播放器
- 如何用C++实现一个LRU Cache
- 如何用C++实现一个LRU Cache(转载)
- 如何用C++实现一个LRU Cache
- 如何用VS2010新建一个类?用来写C++文件的标准格式建立?就是能做到声把声明放在.H里,实现放在.CPP里的
- 用C++实现HTTP服务器 - 如何控制一个套接字的发送带宽
- c++ 如何用一个函数实现两个字符串的比较
- c++中如何实现一个不能被继承的类
- 对面试题“输入n,求一个nXn矩阵,规定矩阵沿45度递增,形成一个zigzag数组(JPEG编码里取像素数据的排列顺序),请问如何用C++实现?”的理解
- C++多态是如何实现的——一个简单明晰的例子告诉你!
- C++实现的 如何删除一个指定的文件
- [转]如何用C++实现一个LRU Cache
- 如何用C++实现一个LRU Cache
- 如何用C++和OpenGL实现一个由点组成的诡异的实心圆。。。
- C++的杂七杂八:如何实现一个简单的bind
- 用C++实现HTTP服务器 - 如何控制一个套接字的发送带宽
- 如何用C++实现一个LRU Cache
- 如何用C++实现一个LRU Cache