【李巍(noslopforever·天堂里的死神)原作,转载请注明出处】
本Blog原来那篇《智能指针三兄弟》:
http://blog.csdn.net/noslopforever/archive/2006/12/19/1449569.aspx
,在智能指针的使用上,使用了侵入式的设计。欲使用智能指针,则必须为每个使用智能指针的类生成一个static的INVALID对象。如果是自己写一个库自己用那大凡没有问题,但如果用在别人的库上,这就吃亏了。
INVLALID对象的主要作用是:在解引用(*),指向(->)等操作发生的时候,当智能指针发现自己所接管的指针是一个NULL,就会把指针重定位到INVALID对象上去。以防用户既不写try(比如像我这样的“异常无视流”的坚定支持者: P。题外话,如果要是一个try的坚定支持者的话,那么Boost的智能指针库就很好用了,剩下的内容您就不用看了 ^_^ ),又不判断指针合法与否而导致程序挂掉。现在不让你挂了,只是满天遍地给你报日志,告诉你引用了某某某非法对象。
对于一个抽象或者非抽象类,INVALID类往往应从它们派生,并删除其主要操作函数的实现,转而仅输出Log后就返回错误值。如果您对用户的C++功底放心,那么也可以选择throw一个异常,这对这些用户也是一个好处——异常多了他们自己就记住该怎么去try catch了。助人为乐,帮人学习,此乃功德无量,功德无量……(众人:扔砖!)
INVALID类和对象应有如下特征:
INVALID对象有且仅有一个,且应以实例方式创建自INVALID类。因为INVALID对象多了也没用,一个就够了。
INVALID类的AddRef和Release方法应该架空。在这套体系下,用户很可能会继续无视指针是否合法(因为现在不合法已经不会让他们的程序挂掉了),因此更可能会误调用INVALID对象的Release和Addref。Addref还好,但Release在很多人写起来往往就是if(--ref == 0) delete this;这种情况自然导致对一个唯一的、在桟上创建(而不是在堆上创建)、而且还到处被引用的对象的delete操作,接下来的结果——上帝对我说:“那就不是你我能知道的了”……
重新说一下INVALID,下面开始本帖想说的主题:
昨天散步的时候想到,关于类和INVALID类,是一一对应的,其实可以把他看作一个类和一个INVALID类组成了一个Pair,这意味着什么呢?如何在编译期实现Pair,你想起来了么?
传说中的Traits!
(下面的代码按照记忆所写,可能语法过不去……)
template<typename T>
struct InvalidClassTraits {
typedef void NULL_CLASS;
};
这里,void的原因很简单,void是一个非常特殊的类型,这个类型无法在堆和桟上进行实例化。
而如果我们要建立一个Pair,就这么写:
template<> struct InvalidClassTraits<ClassA>
{ typedef Null_ClassA NULL_CLASS } ;
这里,ClassA和Null_ClassA是原始类和INVALID类。
用的时候怎么用呢?
下面:
template<typename T>
struct _Invalid {
typedef T ValueType;
static ValueType* ReturnInvalid()
{
static InvalidClassTraits<T>::NULL_CLASS NullObj; // 注意这一句
return &NullObj;
}
};
这就满足了我们return一个INVALID对象指针的要求了,而且这个INVALID对象,来自于桟,而且唯一。
原来代码里 return T::INVALID;现在就应该换成:return _Invalid<T>::ReturnInvalid();了。
放到工程里,现在的做法是:
.h里:
class A{
virtual void do() = 0;
};
class A_NULL{
void do();
};
template<> struct InvalidClassTraits<A>{ typedef A_NULL NULL_CLASS } ;
cpp里:
void A_NULL::do()
{
// throw ; or log ; or other ...
}
即可。
用户使用智能指针还是原来的样子:TSharePtr<A> ptrA = ......
不过注意,所有对这个智能指针的使用必须在顺序上后于
template<> struct InvalidClassTraits<A>{ typedef A_NULL NULL_CLASS } ;
这句声明,否则会导致无法链接的错误。
就写到这里了。欢迎大家拍砖扔手雷丢炸弹。理不辨不明,呵呵。
另外,原创文章,允许转载,转载请注明作者和出处:
李巍(noslopforever·天堂里的死神)
http://blog.csdn.net/noslopforever
发表于 @ 2007年06月05日 09:07:00|评论(loading...)|编辑