这几天自鸣得意的定义了一个异常类,如下:
class CGRSException
{
protected:
public:
CGRSException();
CGRSException(UINT nCode,EXCEPTION_POINTERS *ep);
CGRSException(DWORD dwLastError);
CGRSException(LPCTSTR pszFmt,...);
virtual ~CGRSException();
......
//为了快速说明问题,省去了其他内容
};
表面上看它没什么大的问题,确实也没有问题。
在代码中我使用了下面的抛出异常代码:
throw CGRSException(_T("程序遇到了一个问题!"));
在截获时使用了下面的方式:
try
{
........
}
catch(CGRSException e)
{
}
这看起来也没有问题。真的没有问题吗?
当我在析构函数中调用了一个销毁成员字符串的操作后,我遇到了一个严重的问题,系统总是提示要销毁的字符串指针是无效的,头疼,严重的头疼,我是在构造函数申请的这个字符串,为什么析构函数却说是无效的指针呢?
难道是其他的什么代码改变了这个字符串的指针?我检查了n编后都确定没有问题。为什么呢?
在跟踪过程中,我确定构造函数成功的分配了这个字符串指针,但同时我又发现析构中的这个指针虽然不为NULL,但却是一个无效的指针,并不是构造函数中申请的那个指针,奇怪了,难道老母鸡真会变鸭。
偶然间我看了看异常类对象的this指针,怎么构造时和析构时值不一样?此时我恍然大悟,原来throw时,和catch时,不是同一个对象,在catch中,系统动态的复制了一个对象,就像函数调用一样,catch中得到是一个临时的拷贝。
在我把catch语句改成如下后,一且就正常了:
catch(CGRSException& e)
当然也可以通过为异常类添加一个复制构造函数来解决这个问题,但是我觉得那样既耗资源,又耗时间,没有这种方式直接和优雅。
这个错误使我更深刻的理解了C++异常处理机制,其实可以将catch语句完全看作是一个函数调用,除了这个特定的catch函数名不能变外,其参数完全是由我们自己控制的。基于这个认识,那么将参数改为引用,那么我的问题也就迎刃而解了。
也不知道这个问题我描述清楚没有,各位看客有什么问题尽管跟贴排砖!