前边我们知道,C++中的异常类型有基本数据类型,除此之外,也可以是自定义类类型,对于类类型异常的匹配依旧是至上而下严格匹配,父子间的赋值兼容性原则在异常匹配中依然适用,也就是说抛出的子类异常,catch语句中可以使用父类类型接收处理。
一般的设计原则是:匹配子类异常的catch放在上部;匹配父类异常的catch放在下部
try
{
throw child; //抛出一个子类异常
}
catch(const child& e) //子类异常catch语句块再先
{
}
catch (const Parent& e) //父类异常catch语句块在后
{
}
这里我们为我们的数据结构定义一个异常类族,即有一个异常父类,多个异常子类,结构如下:
我们还是在命名 空间LMSLib内建立该异常类族,头文件为ExcepTion.h,源文件为ExcepTion.cpp
头文件ExcepTion.h如下
#ifndef __EXCEPTION_H__
#define __EXCEPTION_H__
#include "MyObject.h"
namespace MyLib
{
//定义宏THROW_EXCEPTION,抛出异常时直接写异常类型及异常信息即可
#define THROW_EXCEPTION(e, m) (throw e(m, __FILE__, __LINE__))
//异常父类
class ExcepTion : MyObject
{
private:
char* m_message; //异常信息
char* m_location; //异常位置
void init(const char* message, const char* file, int line);
public:
ExcepTion(const char* message);
ExcepTion(const char* file, int line);
ExcepTion(const char* message, const char* file, int line);
ExcepTion(const ExcepTion& obj);
ExcepTion& operator = (const ExcepTion& obj);
virtual const char* message() const;
virtual const char* location() const;
virtual ~ExcepTion() = 0; //析构函数设置为纯虚函数,即此异常父类不能实例化,只能被继承
};
//计算异常
class ArithmeticException : public ExcepTion
{
public:
ArithmeticException():ExcepTion(0){}
ArithmeticException(const char* message) : ExcepTion(message){}
ArithmeticException(const char* file, int line):ExcepTion(file, line){}
ArithmeticException(const char* message, const char* file, int line):ExcepTion(message, file, line){}
ArithmeticException(const ArithmeticException& obj):ExcepTion(obj){}
ArithmeticException& operator = (const ArithmeticException& obj)
{
ExcepTion::operator=(obj);
return *this;
}
};
//空指针异常
class NullPointerException : public ExcepTion
{
public:
NullPointerException():ExcepTion(0){}
NullPointerException(const char* message) : ExcepTion(message){}
NullPointerException(const char* file, int line):ExcepTion(file, line){}
NullPointerException(const char* message, const char* file, int line):ExcepTion(message, file, line){}
NullPointerException(const NullPointerException& obj):ExcepTion(obj){}
NullPointerException& operator = (const NullPointerException& obj)
{
ExcepTion::operator=(obj);
return *this;
}
};
//越界异常
class IndexOutOfBoundsException : public ExcepTion
{
public:
IndexOutOfBoundsException():ExcepTion(0){}
IndexOutOfBoundsException(const char* message) : ExcepTion(message){}
IndexOutOfBoundsException(const char* file, int line):ExcepTion(file, line){}
IndexOutOfBoundsException(const char* message, const char* file, int line):ExcepTion(message, file, line){}
IndexOutOfBoundsException(const IndexOutOfBoundsException& obj):ExcepTion(obj){}
IndexOutOfBoundsException& operator = (const IndexOutOfBoundsException& obj)
{
ExcepTion::operator=(obj);
return *this;
}
};
//内存不足异常
class NoEnoughtMemoryException : public ExcepTion
{
public:
NoEnoughtMemoryException():ExcepTion(0){}
NoEnoughtMemoryException(const char* message) : ExcepTion(message){}
NoEnoughtMemoryException(const char* file, int line):ExcepTion(file, line){}
NoEnoughtMemoryException(const char* message, const char* file, int line):ExcepTion(message, file, line){}
NoEnoughtMemoryException(const NoEnoughtMemoryException& obj):ExcepTion(obj){}
NoEnoughtMemoryException& operator = (const NoEnoughtMemoryException& obj)
{
ExcepTion::operator=(obj);
return *this;
}
};
//参数错误异常
class InvalidParameterException : public ExcepTion
{
public:
InvalidParameterException():ExcepTion(0){}
InvalidParameterException(const char* message) : ExcepTion(message){}
InvalidParameterException(const char* file, int line):ExcepTion(file, line){}
InvalidParameterException(const char* message, const char* file, int line):ExcepTion(message, file, line){}
InvalidParameterException(const InvalidParameterException& obj):ExcepTion(obj){}
InvalidParameterException& operator = (const InvalidParameterException& obj)
{
ExcepTion::operator=(obj);
return *this;
}
};
//成员函数调用状态异常
class InvalidOperationException : public ExcepTion
{
public:
InvalidOperationException():ExcepTion(0){}
InvalidOperationException(const char* message) : ExcepTion(message){}
InvalidOperationException(const char* file, int line):ExcepTion(file, line){}
InvalidOperationException(const char* message, const char* file, int line):ExcepTion(message, file, line){}
InvalidOperationException(const InvalidOperationException& obj):ExcepTion(obj){}
InvalidOperationException& operator = (const InvalidOperationException& obj)
{
ExcepTion::operator=(obj);
return *this;
}
};
}
#endif //__EXCEPTION_H__
源文件头文件ExcepTion.cpp如下
#include "ExcepTion.h"
#include <cstring>
#include <cstdlib>
using namespace std;
namespace MyLib
{
void ExcepTion::init(const char* message, const char* file, int line)
{
if (NULL != message)
{
m_message = strdup(message); //保险起见,把信息复制一份
}
else
{
m_message = NULL;
}
if (NULL != file)
{
char sl[16] = {0};
itoa(line, sl, 10);
m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
if(NULL != m_location)
{
strcpy(m_location, file);
m_location = strcat(m_location, ":");
m_location = strcat(m_location, sl);
}
}
else
{
m_location = NULL;
}
}
ExcepTion::ExcepTion(const char* message)
{
init(message, NULL, 0);
}
ExcepTion::ExcepTion(const char* file, int line)
{
init(NULL, file, line);
}
ExcepTion::ExcepTion(const char* message, const char* file, int line)
{
init(message, file, line);
}
ExcepTion::ExcepTion(const ExcepTion& obj)
{
m_message = strdup(obj.m_message);
m_location = strdup(obj.m_location);
}
ExcepTion& ExcepTion::operator = (const ExcepTion& obj)
{
if (this != &obj)
{
delete m_message;
delete m_location;
m_message = strdup(obj.m_message);
m_location = strdup(obj.m_location);
}
return *this;
}
const char* ExcepTion::message() const
{
return m_message;
}
const char* ExcepTion::location() const
{
return m_location;
}
ExcepTion::~ExcepTion() //顶层父类的析构函数必须要实现函数体,因为子类销毁时必须要调用顶层父类的析构函数
{
if (!m_location)
{
delete m_location;
}
if (!m_message)
{
delete m_message;
}
}
}
以上便是我们定义的异常类族,下边我们在main函数中来简单实用一下
#include <iostream>
#include <string>
#include "ExcepTion.h"
using namespace std;
using namespace MyLib;
int main()
{
try
{
THROW_EXCEPTION(ArithmeticException, "error message"); //抛出一个计算异常
}
catch(const ArithmeticException& e) //子类异常catch语句块再先
{
cout << "catch (const ArithmeticException& e)" << endl;
cout << e.location() << endl;
cout << e.message() << endl;
}
catch (const ExcepTion& e) //父类异常catch语句块在后
{
cout << "catch (const ExcepTion& e)" << endl;
cout << e.location() << endl;
cout << e.message() << endl;
}
system("pause");
return 0;
}
编译执行:
main函数中我们直接使用 定义的宏THROW_EXCEPTION来抛出异常,只要提供异常类型及异常信息即可,后续的数据结构篇章我们也将直接实用这个异常类族来处理异常。