首先, 如果当你有一系列的线性操作, 然后其中某步操作可能导致整个业务失败, 此时要直接跳出线性操作, 并提前提交错误代码再执行一些错误处理, 此时, 你会怎么做,
你可能会使用goto语法
#include <stdio.h>
int Eat(const char* pFood)
{
if (pFood)
{
printf("A cat eats %s\n", pFood);
return 0;
}
else
{
printf("A cat eat nothing, it is hungry!\n");
return -1;
}
}
int Play(const char* pToy)
{
if (pToy)
{
printf("A cat plays a %s\n", pToy);
return 0;
}
else
{
printf("A cat has nothing to play\n");
return -2;
}
}
int CatAction(const char* pFood, const char* pToy)
{
int nRes = 0;
if (nRes = Eat(pFood) != 0)
{
goto CatSad;
}
if (nRes = Play(pToy) != 0)
{
goto CatSad;
}
printf("A cat is happy!\n");
return 0;
CatSad:
printf("A cat is unhappy! (with the errorcode is %d)\n", nRes);
return 0;
}
int main()
{
CatAction("fish", "mice toy");
CatAction(nullptr, nullptr);
}
可能你还会这么干do{}while(false);
int CatAction(const char* pFood, const char* pToy)
{
int nRes = 0;
do
{
if (nRes = Eat(pFood) != 0)
{
break;;
}
if (nRes = Play(pToy) != 0)
{
break;;
}
printf("A cat is happy!\n");
return 0;
} while (false);
printf("A cat is unhappy! (with the errorcode is %d)\n", nRes);
return 0;
}
结果大概会是这样的
接着, 当你阅读了Java的代码, 会发现, 他们有好多的 try, catch, 或许你的前辈会告诉你. C++的异常处理一点儿也不好用. 什么也catch不到.
你本着怀疑的态度, 进行了google, 发现, 什么鬼, 你都没有throw, 要程序怎么catch, 但是, 这个try catch好像可以适用于我们上面说到的业务, 而且关键是, 很优雅. (好吧, 性能什么的, 先无视, try/catch是会牺牲性能)
我们进行了如下改动
#include <stdio.h>
int Eat(const char* pFood) throw(const char*)
{
if (pFood)
{
printf("A cat eats %s\n", pFood);
return 0;
}
else
{
throw "A cat eat nothing, it is hungry!\n";
return -1;
}
}
int Play(const char* pToy) throw(const char*)
{
if (pToy)
{
printf("A cat plays a %s\n", pToy);
return 0;
}
else
{
throw "A cat has nothing to play\n";
return -2;
}
}
int CatAction(const char* pFood, const char* pToy)
{
int nRes = 0;
try
{
Eat(pFood);
Play(pToy);
printf("A cat is happy!\n");
return 0;
}
catch(const char* pError)
{
printf("%s\n", pError);
}
return 0;
}
int main()
{
CatAction("fish", "mice toy");
CatAction(nullptr, nullptr);
}
跑了一下, 结果是这样的
然后这, 并不能满足你, 你觉得, 这样我不能拿到错误代码啊, 难道我要搞个全局的吗, 那样都不酷
你查了很多资料, 发现可以把异常封装成一个对象去抛
你又写了如下的代码
#include <iostream>
class CMyException
{
public:
CMyException(int errorcode, char* pErrorText = nullptr);
~CMyException();
char* GetErrorText(){return m_pErrorText;};
int GetErrorCode(){return m_nErrorCode;};
protected:
int m_nErrorCode;
char* m_pErrorText;
};
CMyException::CMyException( int errorcode, char* pErrorText ) : m_nErrorCode(errorcode), m_pErrorText(0)
{
printf("CMyException create\n");
if (pErrorText != nullptr)
{
size_t tLen = strlen(pErrorText);
m_pErrorText = new char[tLen + 1];
sprintf(&m_pErrorText[0], pErrorText);
}
}
CMyException::~CMyException()
{
printf("CMyException destory\n");
if (m_pErrorText)
{
delete[] m_pErrorText;
m_pErrorText = nullptr;
}
}
int Eat(const char* pFood) throw(CMyException&)
{
if (pFood)
{
printf("A cat eats %s\n", pFood);
return 0;
}
else
{
throw CMyException(-1, "A cat eat nothing, it is hungry!\n");
return -1;
}
}
int Play(const char* pToy) throw(CMyException&)
{
if (pToy)
{
printf("A cat plays a %s\n", pToy);
return 0;
}
else
{
throw CMyException(-2, "A cat has nothing to play\n");
return -2;
}
}
int CatAction(const char* pFood, const char* pToy)
{
int nRes = 0;
try
{
Eat(pFood);
Play(pToy);
printf("A cat is happy!\n");
return 0;
}
catch(CMyException& e)
{
printf("ErrorText:%s, ErrorCode:%d\n", e.GetErrorText(), e.GetErrorCode());
}
return 0;
}
int main()
{
CatAction("fish", "mice toy");
CatAction(nullptr, nullptr);
}
你很开心地点了一下运行
导演, 说好的try/catch怎么没有出来?
细心的你肯定不甘心, 做了调试, 发现是抛出的对象生命周期到了, 被析构了
好像没办法的样子
然后你问了群里的大神, 主要是虾神, 在交流中, 你发现, 有种东西叫做拷贝构造函数
你就加了上去, 试试
#include <iostream>
class CMyException
{
public:
CMyException(int errorcode, char* pErrorText = nullptr);
~CMyException();
CMyException(CMyException& e);
char* GetErrorText(){return m_pErrorText;};
int GetErrorCode(){return m_nErrorCode;};
protected:
int m_nErrorCode;
char* m_pErrorText;
};
CMyException::CMyException( int errorcode, char* pErrorText ) : m_nErrorCode(errorcode), m_pErrorText(0)
{
printf("CMyException create\n");
if (pErrorText != nullptr)
{
size_t tLen = strlen(pErrorText);
m_pErrorText = new char[tLen + 1];
sprintf(&m_pErrorText[0], pErrorText);
}
}
CMyException::CMyException(CMyException& e ) : m_nErrorCode(e.GetErrorCode()), m_pErrorText(0)
{
if (e.GetErrorText() != nullptr)
{
size_t tLen = strlen(e.GetErrorText());
m_pErrorText = new char[tLen + 1];
sprintf(&m_pErrorText[0], e.GetErrorText());
}
}
CMyException::~CMyException()
{
printf("CMyException destory\n");
if (m_pErrorText)
{
delete[] m_pErrorText;
m_pErrorText = nullptr;
}
}
int Eat(const char* pFood) throw(CMyException&)
{
if (pFood)
{
printf("A cat eats %s\n", pFood);
return 0;
}
else
{
throw CMyException(-1, "A cat eat nothing, it is hungry!\n");
return -1;
}
}
int Play(const char* pToy) throw(CMyException&)
{
if (pToy)
{
printf("A cat plays a %s\n", pToy);
return 0;
}
else
{
throw CMyException(-2, "A cat has nothing to play\n");
return -2;
}
}
int CatAction(const char* pFood, const char* pToy)
{
int nRes = 0;
try
{
Eat(pFood);
Play(pToy);
printf("A cat is happy!\n");
return 0;
}
catch(CMyException& e)
{
printf("ErrorText:%s, ErrorCode:%d\n", e.GetErrorText(), e.GetErrorCode());
}
return 0;
}
int main()
{
CatAction("fish", "mice toy");
CatAction(nullptr, nullptr);
}
就是这么神奇.....