c++中try catch的用法

c++中try catch的用法在c++中,可以直接抛出异常之后自己进行捕捉处理,如:(这样就可以在任何自己得到不想要的结果的时候进行中断,比如在进行数据库事务操作的时候,如果某一个语句返回SQL_ERROR则直接抛出异常,在catch块中进行事务回滚)

#include 
#include 
using namespace std;
int main () {
	try
	{
		throw 1;
		throw "error";
	}
	catch(char *str)
	{
		cout << str << endl;
	}
	catch(int i)
	{
		cout << i << endl;
	}
}


使用标准异常类进行处理:标准异常类exception的what()是个virtual函数

#include 
#include 
using namespace std;

int main () {
	try
	{
		int* myarray= new int[100000];
	}
	catch (exception& e)
	{
		cout << "Standard exception: " << e.what() << endl;
	}
	return 0;
}

也可以自己定义异常类来进行处理:

#include 
#include 
using namespace std;

//可以自己定义Exception
class myexception: public exception
{
	virtual const char* what() const throw()
	{
		return "My exception happened";
	}
}myex;

int main () {
	try
	{    
		if(true)    //如果,则抛出异常;
			throw myex;
	}
	catch (exception& e)
	{
		cout << e.what() << endl;  //调用自定义的myexception:: what()
	}
	return 0;
}


我们的异常处理类的features

如何写一个异常处理类是一个不太容易的事情,最近刚好接触了一些不错的代码,看到了一些技巧,这里和大家分享一下。
一个相对完善的异常处理类(以及附加的一些东西)应该能够处理下面的一些功能:
1) 能够方便的定义异常类的继承树
2) 能够方便的throw、catch,也就是在代码中捕获、处理代码的部分应该更短
3) 能够获取异常出现的源文件的名字、方法的名字、行号
4) 能够获取异常出现的调用栈并且打印出来
       由于目前我用的平台是linux,所以里面调用的一些函数也只是在linux下面有用。Windows也肯定是具有相应的函数的,具体可能        需要去查查


首先科普一些内容:
1) 对于没有捕获的异常(no handler),则会终止程序,调用terminate()
2) 在定义函数的时候,我们可以在定义的后面加上throw (exception1, exception2…):
    a) 如果没有写这一段、则可能抛出任意的异常
    b) 如果写throw(),则表示函数不能抛出任意的异常
    c) 如果写throw(A, B), 表示函数抛出A、B的异常
如果抛出的异常不在列表范围内,则异常不能被catch,也就会调用terminate()


工程中用例:

Exception.h

#ifndef EXCEPTION_TEST
#define EXCEPTION_TEST

#include 
#include 


/*
	直接从自己的类 ExceptionDerived 入手看;
如何使用参考:
	void testThrow(int &a, int &b)	
*/



/*
ExClass:		ExceptionDerived
args	    :       要抛出的信息

*/
#define MY_THROW(ExClass, args...)                             \
	do                                                         \
	 {                                                          \
		 ExClass e(args);                                       \
		 e.Init(__FILE__, __PRETTY_FUNCTION__, __LINE__);       \
		 throw e;                                               \
	 }                                                          \
	 while (false)     


/*
ExClass:		ExceptionDerived
Base    :		ExceptionBase
功能: 
			用子类ExceptionDerived 的msg 初始化
			父类ExceptionBase 的mMsg;
*/
#define MY_DEFINE_EXCEPTION(ExClass, Base)                     \
 ExClass(const std::string& msg = "") throw()               \
	 : Base(msg)                                            \
 {}                                                         \
															\
 ~ExClass() throw() {}                                        \
															\
 std::string GetClassName() const            				\
 {                                                          \
	 return #ExClass;                                       \
 }



 
class ExceptionBase : public std::exception
{
	public:
		 ExceptionBase(const std::string& msg = "") throw();

		 virtual ~ExceptionBase() throw();

		 /*初始化:抛异常的文件名, 函数名, 行号*/
		 void Init(const char* file, const char* func, int line);

		 virtual std::string GetClassName() const;

		 virtual std::string GetMessage() const;

		 const char* what() const throw();

		 const std::string& ToString() const;

		 std::string GetStackTrace() const;

	protected:
		 std::string mMsg;
		 const char* mFile;
		 const char* mFunc;
		 int mLine;

	private:
		 enum { MAX_STACK_TRACE_SIZE = 50 };
		 void* mStackTrace[MAX_STACK_TRACE_SIZE];
		 size_t mStackTraceSize;
		 mutable std::string mWhat;
};



/*
自己的类ExceptionDerived
*/
class ExceptionDerived : public ExceptionBase
{
	public:
		MY_DEFINE_EXCEPTION(ExceptionDerived, ExceptionBase);
};



#endif



Exception.cpp
#include 
#include 
#include 

#include 
#include 

#include "Exception.h"

using namespace std;

ExceptionBase::ExceptionBase(const std::string& msg) throw()
 : mMsg(msg),
   mFile(""),
   mFunc(""),
   mLine(-1),
   mStackTraceSize(0)
{}

ExceptionBase::~ExceptionBase() throw()
{}

void ExceptionBase::Init(const char* file, const char* func, int line)
{
	 mFile = file;
	 mFunc = func;
	 mLine = line;
	 mStackTraceSize = backtrace(mStackTrace, MAX_STACK_TRACE_SIZE);
}

std::string ExceptionBase::GetClassName() const
{
 	return "ExceptionBase";
}

const char* ExceptionBase::what() const throw()
{
 	return ToString().c_str();
}

const std::string& ExceptionBase::ToString() const
{
 if (mWhat.empty())
 {
	 stringstream sstr("");
	 if (mLine > 0)
	 {
		 sstr << mFile << "(" << mLine << ")";
	 }
	 sstr <<  ": " << GetClassName();
	 if (!GetMessage().empty())
	 {
		 sstr << ": " << GetMessage();
	 }
	 //sstr << "\nStack Trace:\n";
	 //sstr << GetStackTrace();
	 mWhat = sstr.str();
 }
 return mWhat;
}

std::string ExceptionBase::GetMessage() const
{
 return mMsg;
}

std::string ExceptionBase::GetStackTrace() const
{
	 if (mStackTraceSize == 0)
		 return "\n";
	 char** strings = backtrace_symbols(mStackTrace, 10);
	 if (strings == NULL) // Since this is for debug only thus
						  // non-critical, don't throw an exception.
		 return "\n";

	 std::string result;
	 for (size_t i = 0; i < mStackTraceSize; ++i)
	 {
		 std::string mangledName = strings[i];
		 std::string::size_type begin = mangledName.find('(');
		 std::string::size_type end = mangledName.find('+', begin);
		 if (begin == std::string::npos || end == std::string::npos)
		 {
			 result += mangledName;
			 result += '\n';
			 continue;
		 }
		 ++begin;
		 int status;
		 char* s = abi::__cxa_demangle(mangledName.substr(begin, end-begin).c_str(),
									   NULL, 0, &status);
		 if (status != 0)
		 {
			 result += mangledName;
			 result += '\n';
			 continue;
		 }
		 std::string demangledName(s);
		 free(s);
		 // Ignore ExceptionBase::Init so the top frame is the
		 // user's frame where this exception is thrown.
		 //
		 // Can't just ignore frame#0 because the compiler might
		 // inline ExceptionBase::Init.
		 result += mangledName.substr(0, begin);
		 result += demangledName;
		 result += mangledName.substr(end);
		 result += '\n';
	 }
	 free(strings);
	 return result;
}



/*
MY_THROW 中最终调用了ExceptionBase中的Init 获得调用MY_THROW的
文件名 函数名行号,最后throw e;;
接着最终调用了ExceptionBase中的what 打印文件名 函数名行号
以及异常信息;
*/
void testThrow(int &a, int &b)
{
	 try
	 {
	 	 if(a > b)
	 	 {
			MY_THROW(ExceptionDerived, "a is big than b ,so throw");		//抛异常
		 }
		 else
		 {
			cout<<"a not big than b"< b时候抛出异常
*/
int main()
{
	int a = 5, b = 10;
	
	testThrow(a, b);


	a = 10, b = 5;
	testThrow(a, b);
}


你可能感兴趣的:(c++)