C++数据结构异常类的构建

    前边我们知道,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来抛出异常,只要提供异常类型及异常信息即可,后续的数据结构篇章我们也将直接实用这个异常类族来处理异常

猜你喜欢

转载自blog.csdn.net/lms1008611/article/details/81609664