您的位置:首页 > 移动开发 > Objective-C

如何用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 能不能支持 ? 带这种疑问试验了 如下的写法 :

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 写法





                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: