打造一个异常类

现在C++库必然包含充要的异常类族,异常类族是数据结构类所依赖的"基础设施", 如下图是该异常类族的类图,顶层的类是一个抽象类,它是不能定义对象的,只能用来被继承,从左向右的异常类分别为计算异常,空指针异常,越界异常,内存不足异常,参数错误异常,
在这里插入图片描述
顶层抽象父类的接口定义:

Exception.h
class Exception
{
  public:
  Exception(const char *message);
  Exception(const char *file,int line);
  Exception(const char *message,const char *file,int line);
  Exception(const Exception& e);
  Exception& operator = (const Exception& e);
 
  virtual const char * message() const;//打印出异常的说明信息
  virtual const char * location()const;//打印出异常的出错位置
 
  virtual ~Exception() = 0;//纯虚析构函数
}

在项目的设计原则中,尽量使用面向对象技术进行架构,尽量使用异常处理机制分离正常逻辑和异常逻辑,代码如下

#ifndef _EXCEPTION_H
#define _EXCEPTION_H
namespace CGSLib
{
  #define THROW_EXCEPTION(m,s) (m(s,__FILE__,__LINE__))
  class Exception
  {
      protected:
      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& e);
      Exception& operator = (const Exception& e);

      virtual const char * message() const;//打印出异常的说明信息
      virtual const char * location()const;//打印出异常的出错位置

      virtual ~Exception();//纯虚析构函数
   };
  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& e):Exception(e){}
      ArithmeticException& operator=(const ArithmeticException& e)
      {
         Exception::operator =(e);
         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& e):Exception(e){}
      NullPointerException& operator=(const NullPointerException& e)
      {
         Exception::operator =(e);
         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& e):Exception(e){}
      IndexOutOfBoundsException& operator=(const IndexOutOfBoundsException& e)
      {
         Exception::operator =(e);
         return *this;
      }

  };
  class NoEnougMemoryException : public Exception
  {
     public:
      NoEnougMemoryException():Exception(0){}
      NoEnougMemoryException(const char *message):Exception(message){}
      NoEnougMemoryException(const char *file,int line):Exception(file,line){}
      NoEnougMemoryException(const char *message,const char *file,int line):Exception(message,file,line){}
      NoEnougMemoryException(const NoEnougMemoryException& e):Exception(e){}
      NoEnougMemoryException& operator=(const NoEnougMemoryException& e)
      {
         Exception::operator =(e);
         return *this;
      }

  };
  class InvalidParamterException : public Exception
  {
     public:
      InvalidParamterException():Exception(0){}
      InvalidParamterException(const char *message):Exception(message){}
      InvalidParamterException(const char *file,int line):Exception(file,line){}
      InvalidParamterException(const char *message,const char *file,int line):Exception(message,file,line){}
      InvalidParamterException(const InvalidParamterException& e):Exception(e){}
      InvalidParamterException& operator=(const InvalidParamterException& e)
      {
         Exception::operator =(e);
         return *this;
      }

  };
}
#endif // EXCEPTION_H
Exception.cpp
#include "Exception.h"
#include <cstring>
#include <cstdlib>
using  namespace std;
namespace CGSLib
{
   void Exception::init(const char *message,const char *file,int line)
   {
    m_message = strdup(message);
    if(file!=NULL)
    {
        char str[16]={0};
        itoa(line,str,10);
        m_location = static_cast<char*>(malloc(sizeof(file)+sizeof(line)+2));
        m_location = strcpy(m_location,file);
        m_location = strcat(m_location,":");
        m_location = strcat(m_location,str);
    }
    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& e)
   {
       m_message = strdup(e.m_message);
       m_location = strdup(e.m_location);
   }
   Exception& Exception::operator = (const Exception& e)
   {
       if(this!=&e)
       {
           free(m_message);
           free(m_location);
           m_message = strdup(e.m_message);
           m_location = strdup(e.m_location);
       }
       return *this;
   }
  const char * Exception::message() const
  {
    return m_message;
  }
  const char * Exception::location()const
  {
    return m_location;
  }
  Exception::~Exception()
  {
      free(m_message);
      free(m_location);
  }
}

main.cpp

#include <iostream>

using namespace std;
#include <iostream>
#include "Exception.h"

using namespace std;
using namespace CGSLib;
int main()
{
    try
    {
        throw THROW_EXCEPTION(InvalidParamterException,"test");
    }catch(const Exception & e)
    {
      cout<<"catch(const Exception& e)"<<endl;
      cout<<e.message()<<endl;
      cout<<e.location()<<endl;
    }
}

结果:

在这里插入图片描述

当代软件架构实践的经验
尽量使用单重继承的方式进行系统设计
尽量保持系统中只存在单一的继承树
尽量使用组合关系代替继承关系

发布了83 篇原创文章 · 获赞 3 · 访问量 1254

猜你喜欢

转载自blog.csdn.net/qq_41936794/article/details/105092688
今日推荐