Ogre 异常处理
Ogre用c++内建的异常处理机制来处理错误
使用异常处理的好处
首先,使用异常 处理了,可以使得C++程序的两个部分相互通信(这两个部分通常是分别开发的)。检测到异常的部分可以抛出异常,而另一部分可以捕获异常并做出处理。
其次,使用异常处理,可以避免用返回值来定义错误,当有错误发生的时候,一个异常就会被抛出,这个异常里面封装了发生错误的详细信息。
Eg:
Try{
app.go();
}catcn(Ogre::Exception &e ){
//处理异常
}
首先,这段代码分为两个部分,分别由try与catch包围起来,如果app.go()有错误产生,则Ogre::Exception类型的异常会被抛出,catch部分捕获并处理这个异常。
其次,如果没有异常这段代码可能就是这样的:
If(!app.go())
{
//处理错误
}
可以看出如果没有异常机制,我们就不得不使用函数的返回值来定义错误,这样,不但错误信息不准确,而且导致程序的错误处理代码与应用代码混在一起,不易于维护。
Ogre对异常处理的支持
Ogre::Exception
Ogre定义了自己的异常类型Ogre::Exception,它记录了错误地详细信息(错误编号、详细描述、错误发生的文件名、行数等)。当有错误发生的时候,Ogre会抛出这个类型的异常,并把这个异常记录的错误信息写入到LogManager的默认日志文件中。
Ogre::Exception提供了一个成员函数getFullDescription,它的返回值是String类型的,保存了对错误的详细描述。
Ogre::Exception维护了一个函数名称堆栈,提供了一个入栈函数pushFunction,它接受一个String类型的参数。和一个出栈函数_popFunction,我们需要在每个函数的起始位置调用_pushFunction,并把该函数的额函数名当做参数传入,在结束位置调用_popFunction.
通过查看代码可以看到真个异常定义是通过工厂模式来实现的,首先是定义一个异常类,然后通过继承该类并添加不同的附加信息形成信息携带不同的异常类,最后用一个异常工厂来完成异常的判断。
#ifndef __Exception_H_
#define __Exception_H_
// Precompiler options
#include "OgrePrerequisites.h"
#include "OgreHeaderPrefix.h"
#include "OgreString.h"
#include <exception>
// Backwards compatibility with old assert mode definitions
#if OGRE_RELEASE_ASSERT == 1
# define OGRE_ASSERT_MODE 1
#endif
// Check for OGRE assert mode
//------------------------------------------------------以下是针对于不同判定模式所采用的错误机制------------------------------------------------------------//
// RELEASE_EXCEPTIONS mode
#if OGRE_ASSERT_MODE == 1
# ifdef _DEBUG
# define OgreAssert( a, b ) assert( (a) && (b) )
# else
# if OGRE_COMP != OGRE_COMPILER_BORL
# define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (b), "no function info")
# else
# define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (b), __FUNC__ )
# endif
# endif
// EXCEPTIONS mode
#elif OGRE_ASSERT_MODE == 2
# ifOGRE_COMP != OGRE_COMPILER_BORL
# define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (b), "no function info")
# else
# define OgreAssert( a, b ) if( !(a) ) OGRE_EXCEPT( Ogre::Exception::ERR_RT_ASSERTION_FAILED, (b), __FUNC__ )
# endif
// STANDARD mode
#else
# define OgreAssert( a, b ) assert( (a) && (b) )
#endif
namespace Ogre {
class _OgreExport Exception : public std::exception //-----------------------定义了异常类的全部内容
{
protected:
long line;
int number;
String typeName;
String description;
String source;
String file;
mutable String fullDesc;
public:
enum ExceptionCodes { //===================================定义了异常代码的枚举类型
ERR_CANNOT_WRITE_TO_FILE,
ERR_INVALID_STATE,
ERR_INVALIDPARAMS,
ERR_RENDERINGAPI_ERROR,
ERR_DUPLICATE_ITEM,
ERR_ITEM_NOT_FOUND,
ERR_FILE_NOT_FOUND,
ERR_INTERNAL_ERROR,
ERR_RT_ASSERTION_FAILED,
ERR_NOT_IMPLEMENTED
};
Exception( int number, const String& description, const String& source );
Exception( int number, const String& description, const String& source, const char* type, const char* file, long line );
Exception(const Exception& rhs);
/// Needed for compatibility with std::exception
~Exception() throw() {}
void operator = (const Exception& rhs);
virtual const String& getFullDescription(void) const;
virtual int getNumber(void) const throw();
virtual const String &getSource() const { return source; }
virtual const String &getFile() const { return file; }
virtual long getLine() const { return line; }
virtual const String &getDescription(void) const { return description; }
/// Override std::exception::what
const char* what() const throw() { return getFullDescription().c_str(); }
};
template <int num>
struct ExceptionCodeType //里面包含了异常的编码
{
enum { number = num };
};
//通过继承上面的Exception类来定义不同的异常类型
// Specialised exceptions allowing each to be caught specifically
// backwards-compatible since exception codes still used
class _OgreExport UnimplementedException : public Exception
{
public:
UnimplementedException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
: Exception(inNumber, inDescription, inSource, "UnimplementedException", inFile, inLine) {}
};
class _OgreExport FileNotFoundException : public Exception
{
public:
FileNotFoundException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
: Exception(inNumber, inDescription, inSource, "FileNotFoundException", inFile, inLine) {}
};
class _OgreExport IOException : public Exception
{
public:
IOException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
: Exception(inNumber, inDescription, inSource, "IOException", inFile, inLine) {}
};
class _OgreExport InvalidStateException : public Exception
{
public:
InvalidStateException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
: Exception(inNumber, inDescription, inSource, "InvalidStateException", inFile, inLine) {}
};
class _OgreExport InvalidParametersException : public Exception
{
public:
InvalidParametersException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
: Exception(inNumber, inDescription, inSource, "InvalidParametersException", inFile, inLine) {}
};
class _OgreExport ItemIdentityException : public Exception
{
public:
ItemIdentityException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
: Exception(inNumber, inDescription, inSource, "ItemIdentityException", inFile, inLine) {}
};
class _OgreExport InternalErrorException : public Exception
{
public:
InternalErrorException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
: Exception(inNumber, inDescription, inSource, "InternalErrorException", inFile, inLine) {}
};
class _OgreExport RenderingAPIException : public Exception
{
public:
RenderingAPIException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
: Exception(inNumber, inDescription, inSource, "RenderingAPIException", inFile, inLine) {}
};
class _OgreExport RuntimeAssertionException : public Exception
{
public:
RuntimeAssertionException(int inNumber, const String& inDescription, const String& inSource, const char* inFile, long inLine)
: Exception(inNumber, inDescription, inSource, "RuntimeAssertionException", inFile, inLine) {}
};
class ExceptionFactory //异常工厂 ,通过此类可以调用相关的静态函数create上面定义的所有异常类型,构造是通过异常号来判断的,返回的是 异常类的句柄
{
private:
/// Private constructor, no construction
ExceptionFactory() {}
public:
static UnimplementedException create(
ExceptionCodeType<Exception::ERR_NOT_IMPLEMENTED> code,
const String& desc,
const String& src, const char* file, long line)
{
return UnimplementedException(code.number, desc, src, file, line);
}
static FileNotFoundException create(
ExceptionCodeType<Exception::ERR_FILE_NOT_FOUND> code,
const String& desc,
const String& src, const char* file, long line)
{
return FileNotFoundException(code.number, desc, src, file, line);
}
static IOException create(
ExceptionCodeType<Exception::ERR_CANNOT_WRITE_TO_FILE> code,
const String& desc,
const String& src, const char* file, long line)
{
return IOException(code.number, desc, src, file, line);
}
static InvalidStateException create(
ExceptionCodeType<Exception::ERR_INVALID_STATE> code,
const String& desc,
const String& src, const char* file, long line)
{
return InvalidStateException(code.number, desc, src, file, line);
}
static InvalidParametersException create(
ExceptionCodeType<Exception::ERR_INVALIDPARAMS> code,
const String& desc,
const String& src, const char* file, long line)
{
return InvalidParametersException(code.number, desc, src, file, line);
}
static ItemIdentityException create(
ExceptionCodeType<Exception::ERR_ITEM_NOT_FOUND> code,
const String& desc,
const String& src, const char* file, long line)
{
return ItemIdentityException(code.number, desc, src, file, line);
}
static ItemIdentityException create(
ExceptionCodeType<Exception::ERR_DUPLICATE_ITEM> code,
const String& desc,
const String& src, const char* file, long line)
{
return ItemIdentityException(code.number, desc, src, file, line);
}
static InternalErrorException create(
ExceptionCodeType<Exception::ERR_INTERNAL_ERROR> code,
const String& desc,
const String& src, const char* file, long line)
{
return InternalErrorException(code.number, desc, src, file, line);
}
static RenderingAPIException create(
ExceptionCodeType<Exception::ERR_RENDERINGAPI_ERROR> code,
const String& desc,
const String& src, const char* file, long line)
{
return RenderingAPIException(code.number, desc, src, file, line);
}
static RuntimeAssertionException create(
ExceptionCodeType<Exception::ERR_RT_ASSERTION_FAILED> code,
const String& desc,
const String& src, const char* file, long line)
{
return RuntimeAssertionException(code.number, desc, src, file, line);
}
};
#ifndef OGRE_EXCEPT
#define OGRE_EXCEPT(num, desc, src) throw Ogre::ExceptionFactory::create( \
Ogre::ExceptionCodeType<num>(), desc, src, __FILE__, __LINE__ );
#endif
} // Namespace Ogre
#include "OgreHeaderSuffix.h"
#endif
Ogre异常处理举例:
//Log.cpp
materialApplication app;
try{
app.go();
}catch(Exception & e){
#if OGRE_PLATFORM==PLATFORM_WIN32
//如果是WIN32平台,就弹出一个错误对话框,显示错误地详细信息。
MessageBox(NULL,e.getFullDescription().c_str(),"An exception has occured!",MB_OK|MB_ICONERROR|MB_TASKMODAL);
#else
//如果不是Win32平台,则直接输出错误的详细信息
fprintf(stderr,"An exception has occured:%s\n,e.getFullDescription().c_str());
//Log.h
//定义一个函数Wudi1,在内部无端地抛出一个异常
void Wudi1()
{
OgreGuard("Wudi1"); //将函数名称压入堆栈
Except(888,"wudi","wudi1");//抛出一个异常
OgreUnguard(); //弹出栈顶元素
}
//定义一函数Wudi2,在内部调用Wudi1
void Wudi2()
{
OgreGuard("Wudi2");//将函数名称 压入堆栈
Wudi1(); //调用Wudi1
OgreUnguard(); //弹出栈顶元素
}
class MaterialApplication:public ExampleApplication
{
public:
MaterialApplication(){}
protected:
//重载createScene函数
void createScene(void)
{
Wudi2(); //调用Wudi2函数
}
};