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函数
}
};