接下来应该是给property_bag写大量的操作符重载了……唔,稍微等等,怎么总是有一个warning消不掉呢?就是下面这个(使用VS 2005):
在这里,我联想到成员变量指针的概念:它仅仅是一个偏移量而已。那么我是否可以用这个偏移量和变量自己的指针反过来算出父类的指针地址呢?答案是肯定的,但是需要用到比较丑陋的trick。
具体代码如下:
namespace
rdxLib
{
template <typename Parent, typename Type>
class property_bag : public detail::basic_type_impl<Type, detail::is_derivable<Type>::value>
{
typedef property_bag<Parent, Type> MyType;
typedef
MyType (Parent::*MyOffset);
typedef
typename ::boost::call_traits<Type>::param_type param_type;
typedef
typename ::boost::call_traits<Type>::reference reference;
typedef
typename ::boost::call_traits<Type>::const_reference const_reference;
typedef param_type (Parent::*Get)()
const;
typedef void (Parent::*Set)(param_type);
Parent * parent_;
Get getFunction_;
Set setFunction_;
public:
property_bag(MyOffset offset, Get get, Set set)
: parent_(
reinterpret_cast<Parent*>((intptr_t)this - (ptrdiff_t)(&(((Parent*)0)->*offset))))
, getFunction_(get)
, setFunction_(set)
{
}
private:
property_bag()
{
}
};
}
关键的代码用黄色标亮,主要由两部分。首先是定义偏移量的类型,也就是那个MyOffset类型,接下来是那个暴复杂的表达式。
简单说说表达式:&(((Parent*)0)->*offset)这个表达式算出了变量在父类中的偏移量具体数值,而ptrdiff_t则是C++标准中规定的指针偏移量类型,强制转换一下可以避免warning,接着是this,转成intptr_t类型之后就可以做加减法了,最后是这两个值相减(注意,是相减,因为父类的this地址在成员的this之前)并强制转换成Parent*指针,结果就是父类的指针。
不过很可惜,warning并没有消除,因为property_bag用到了自己的this!不过这就好办多了,我可以手动的禁掉这个warning:
#pragma
warning(push)
#pragma
warning(disable: 4355)

//
...
#pragma
warning(pop)
这下好了,起码用这个库的用户不再被warning所困扰了。
warning C4355: 'this' : used in base member initializer list
这个C4355是没有办法简单消除的,除非不用this,但又不可能,因为我property_bag的构造函数需要用到父类的指针。那么,能够做改变的就是我的构造函数了。
在这里,我联想到成员变量指针的概念:它仅仅是一个偏移量而已。那么我是否可以用这个偏移量和变量自己的指针反过来算出父类的指针地址呢?答案是肯定的,但是需要用到比较丑陋的trick。
具体代码如下:































关键的代码用黄色标亮,主要由两部分。首先是定义偏移量的类型,也就是那个MyOffset类型,接下来是那个暴复杂的表达式。
简单说说表达式:&(((Parent*)0)->*offset)这个表达式算出了变量在父类中的偏移量具体数值,而ptrdiff_t则是C++标准中规定的指针偏移量类型,强制转换一下可以避免warning,接着是this,转成intptr_t类型之后就可以做加减法了,最后是这两个值相减(注意,是相减,因为父类的this地址在成员的this之前)并强制转换成Parent*指针,结果就是父类的指针。
不过很可惜,warning并没有消除,因为property_bag用到了自己的this!不过这就好办多了,我可以手动的禁掉这个warning:






这下好了,起码用这个库的用户不再被warning所困扰了。