假设有个类别widget;我们希望能够针对该类别做有效性测试,通常我们可能会为widget定义一个is_valid()成员函数
widget w; if (w.is_valid()) {...} |
然而有时候我们可能更希望接口更直接点,比如:
error e; if (e) {...} |
这时候可以采取的一个方法是提供一个转型:
比如转至一个int
class error { public: error (int code) : m_error_code(code) {} operator int() const {return m_error_code; } private: int m_error_code; }; |
通常我们并不鼓励这么做,自动转型暴露了内部数据,总是存在难以发现的隐患(我们应该尽可能遵循伟大的c_str()传统);
另外一种转型operator bool也不被鼓励
class error { ... operator bool() const { return m_error_code != 0; } }; |
原因是你有可能写出:
error e(1), e2(2); if (e == e2) { ... } |
在没有定义operator==的情况下,if (e == e2) 居然也可以通过,而且返回真。原因是e和e2都转型为bool后再做比较。
当然你可以定义operator==以消除这种状况的发生。
class error { ... operator bool() const { return m_error_code != 0; } bool operator==(const error& e) { return m_error_code == e.m_error_code; } }; |
这时if (e == e2) { ... } 可以返回正确的结果,同时你也达到进行有效性测试的目的。
对于像smart_ptr这样的模板类别,情况会有点微妙的变化。你仍然可以进行有效性测试:
smart_ptr<int> s; if (s) { ... } |
但operator==却行为异常。因为你可能对着两个不同类型的smart_ptr进行比较,而对于不同类型的smart_ptr,并未有operator==被实作出来(你只会针对同型的smart_ptr实作operator==):
smart_ptr<A> s1; smart_ptr<B> s2; if (s1 == s2) {... } |
结果是显而易见的,s1,s2分别实施转型至bool,if比较返回true
正确的做法是基于不同的smart_ptr类型产生不同的可测试有效性的类型:下面是一个方法(MordenC++p178)
template <class T> class smart_ptr { class nested_unspecified_type { void opeartor delete(void*); }; public: opeartor nested_unspecified_type*() const { if (!m_pointee) return 0; static nested_unspecified_type n; return &n; } }; |
nested_unspecified_type会声明而未定义void opeartor delete(void*); 的原因是阻止写出如下的delete代码:
delete smart_ptr<int>(new int);
另一个更加精妙的方法来自boost\system\error_code.cpp,即转型至一个函数指针
template <class T> class smart_ptr { typedef void (nested_unspecified_type)(); static void nested_unspecified_type_(){} public: opeartor nested_unspecified_type() const { if (!m_pointee) return 0; return nested_unspecified_type_; } }; |
延伸讨论:
上述除了opeartor==的行为需要考虑以外,其他的比较操作符也需要考虑,比如opeator!=, operator<等。如果没有定义这些操作符,那么smart_ptr或者error都会转型以完成比较,所以行为也就会未定义。
结论是:要定义有效性测试符,请采用转型为内部函数指针的转型符,同时也必须定义各种比较操作符。
版权声明:51Testing软件测试网原创作品,转载请保留链接,标明本文原始出处、作者信息和本声明,否则将追究法律责任。
本文出自51Testing软件测试网,感谢会员kukumaru在每周一问(09-03-30)中的精彩回答。http://bbs.51testing.com/forum-157-1.html