C++异常处理 - 对象篇

首先, 如果当你有一系列的线性操作, 然后其中某步操作可能导致整个业务失败, 此时要直接跳出线性操作, 并提前提交错误代码再执行一些错误处理, 此时, 你会怎么做, 


你可能会使用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;
}

结果大概会是这样的



有一天你发现, 每一步都要判断一步成功与否, 真的...很麻烦, 是的, 也不酷, 只会让你的程序看上去有一堆的, if else

接着, 当你阅读了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);
}


就是这么神奇.....

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值