[Exception]
相关文件:Exception.h,Exception.cpp
这就是前面多次提到过的异常。它派生自std::exception,调用其what方法可以得到有关本次异常的描述信息,在某个断言失败时会抛出异常。
Exception中有一个标识异常类型的inner class——Type,它具有public属性,内部仅有一个常量成员变量m_Type,代表具体类型。唯一的ctor在初始化成员列表中为m_type赋值,此外还有一个operator==函数:
class Type
{
public:
Type( std::string type ) : m_type ( type ) {}
bool operator ==( const Type &other ) const
{
return m_type == other.m_type;
}
private:
const std::string m_type;
};
将类型信息用类来封装,应该是典型的OO风格了,这在refactoring一书中被称为“Replace Type Code with Class”技法,另外,读者还可以在该书中找到其它几项相关内容:Replace Conditional with Polymorphism,Replace Type Code with Subclasses,Replace Type Code with State/Strategy,Replace Data Value with Object。
与Type相关的两个函数是type和isInstanceOf:
// 返回Exception的类型
Exception::Type Exception::type()
{
return Type( "CppUnit::Exception" );
}
// 判断exceptionType是否是“CppUnit::Exception”
bool Exception::isInstanceOf( const Type &exceptionType ) const
{
return exceptionType == type();
}
isInstanceOf实现了一个简单的运行期类型检查,类似于MFC中的IsKindOf。在Exception的派生类中还将见到它。
Exception有两个私有成员变量:
private:
std::string m_message; // 与本次异常相关的描述信息
SourceLine m_sourceLine; // 异常发生的具体位置
查看Exception的ctor发现有两个不同版本:
Exception( std::string message = "",
SourceLine sourceLine = SourceLine() );
#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED
Exception( std::string message, long lineNumber, std::string fileName );
#endif
关于这个CPPUNIT_ENABLE_SOURCELINE_DEPRECATED的来历,在随CppUnit所附的ChangeLog中有过“记载”。早先版本的CppUnit中,Exception并未引用SourceLine类(也就是说没有第一个ctor,当时SourceLine还没“出世”呢),而是代之以fileName和lineNumber这两个成员变量,这一点从第二个ctor的声明中也能看出来。在随后的一次refactoring过程中,这两个可怜的家伙被“Introduce Parameter Object”消灭掉了,于是SourceLine取而代之。但是,作为一个发布了的framework,需要考虑到兼容问题,因此以前的接口必须保留,所以第二个ctor仍然存在,只是其内部实现已偷梁换柱了:
Exception::Exception( std::string message, long lineNumber, std::string fileName ) :
m_message( message ),
m_sourceLine( fileName, lineNumber ) // 仍然转交给SourceLine
{}
既然是“DEPRECATED”,那么这样的接口当然是不推荐使用的,在Exception源码中还有多处与此有关,这里就不多说了。总之,缺省情况下CPPUNIT_ENABLE_SOURCELINE_DEPRECATED没有被定义,因此被#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED……#endif所包围的代码大可不必关心。不过,像这类“历史遗留”问题,想必很多库设计中都会遇到。
还有几个函数,代码如下:
const char* Exception::what() const throw()
{
return m_message.c_str ();
}
Exception *Exception::clone() const
{
return new Exception( *this );
}
Exception::operator =( const Exception& other )
{
if ( &other != this )
{
m_message = other.m_message;
m_sourceLine = other.m_sourceLine;
}
return *this;
}
[NotEqualException]
相关文件:NotEqualException.h,NotEqualException.cpp
派生自Exception,当判断相等的断言失败时会抛出该异常。和基类相比,多了三个private成员变量:
private:
std::string m_expected; // 预期值
std::string m_actual; // 实际值,是否仅支持字符串比较呢,稍后再做讲解
std::string m_additionalMessage; // 附加信息
NotEqualException还覆盖了基类的type、isInstanceOf、clone、operator=这几个函数:
// 返回NotEqualException类型
Exception::Type NotEqualException::type()
{
return Type( "CppUnit::NotEqualException" );
}
// 调用了基类的isInstanceOf,因此若传入的值为Exception的Type,
// 返回亦为true,这一点与常理相符
bool NotEqualException::isInstanceOf( const Type &exceptionType ) const
{
return exceptionType == type() ||
Exception::isInstanceOf( exceptionType );
}
Exception *NotEqualException::clone() const
{
return new NotEqualException( *this );
}
NotEqualException &
NotEqualException::operator =( const NotEqualException &other )
{
Exception::operator =( other ); // 切勿忘记调用基类的operator=
if ( &other != this )
{
m_expected = other.m_expected;
m_actual = other.m_actual;
m_additionalMessage = other.m_additionalMessage;
}
return *this;
}
