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
#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);
}