菜单 学习猿地 - LMONKEY

VIP

开通学习猿地VIP

尊享10项VIP特权 持续新增

知识通关挑战

打卡带练!告别无效练习

接私单赚外块

VIP优先接,累计金额超百万

学习猿地私房课免费学

大厂实战课仅对VIP开放

你的一对一导师

每月可免费咨询大牛30次

领取更多软件工程师实用特权

入驻
86
0

【数据结构】11_异常类构建

原创
05/13 14:22
阅读数 1596
  • 异常的类型可以是自定义类类型
  • 对于类类型异常的匹配依旧是至上而下严格匹配
  • 赋值兼容性原则在异常匹配中依然适用
  • 一般而言

    • 匹配子类异常的 catch 放在上部
    • 匹配父类异常的 catch 放下下部

现代C++库必然包含充要的异常类

异常类是数据结构类所依赖的”基础设施“!

image.png

异常类功能定义

异常类 功能定义
ArithmeticException 计算异常
NullPointerException 空指针异常
IndexOutOfBoundsException 越界异常
NoEnoughMemoryException 内存不足异常
InvalidParameterExcetion 参数错误异常

异常类的接口定义

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();
};

编程实验:创建异常类族

文件:Exception.h

#ifndef EXCEPTION_H
#define EXCEPTION_H

namespace DTLib
{

#define THROW_EXCEPTION(e, m) (throw e(m, __FILE__, __LINE__))

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();

protected:
    char *m_message = nullptr;
    char *m_location = nullptr;
};

class ArithmeticExcption : public Exception
{
public:
    ArithmeticExcption() : Exception(nullptr) { }
    ArithmeticExcption(const char *message) : Exception(message) { }
    ArithmeticExcption(const char *file, int line) : Exception(file, line) { }
    ArithmeticExcption(const char *message, const char *file, int line) : Exception(message, file, line) { }

    ArithmeticExcption(const ArithmeticExcption &e) : Exception(e) { }

    ArithmeticExcption &operator= (const ArithmeticExcption &e)
    {
        Exception::operator=(e);

        return *this;
    }
    ~ArithmeticExcption() override { }
};

class NullPointerException : public Exception
{
public:
    NullPointerException() : Exception(nullptr) { }
    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 ArithmeticExcption &e) : Exception(e) { }

    NullPointerException &operator= (const ArithmeticExcption &e)
    {
        Exception::operator=(e);

        return *this;
    }
    ~NullPointerException() override { }
};

class IndexOutOfBoundsException : public Exception
{
public:
    IndexOutOfBoundsException() : Exception(nullptr) { }
    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 ArithmeticExcption &e) : Exception(e) { }

    IndexOutOfBoundsException &operator= (const ArithmeticExcption &e)
    {
        Exception::operator=(e);

        return *this;
    }
    ~IndexOutOfBoundsException() override { }
};

class NoEnoughMemoryException : public Exception
{
public:
    NoEnoughMemoryException() : Exception(nullptr) { }
    NoEnoughMemoryException(const char *message) : Exception(message) { }
    NoEnoughMemoryException(const char *file, int line) : Exception(file, line) { }
    NoEnoughMemoryException(const char *message, const char *file, int line) : Exception(message, file, line) { }

    NoEnoughMemoryException(const ArithmeticExcption &e) : Exception(e) { }

    NoEnoughMemoryException &operator= (const ArithmeticExcption &e)
    {
        Exception::operator=(e);

        return *this;
    }
    ~NoEnoughMemoryException() override { }
};

class InvalidParameterExcetion : public Exception
{
public:
    InvalidParameterExcetion() : Exception(nullptr) { }
    InvalidParameterExcetion(const char *message) : Exception(message) { }
    InvalidParameterExcetion(const char *file, int line) : Exception(file, line) { }
    InvalidParameterExcetion(const char *message, const char *file, int line) : Exception(message, file, line) { }

    InvalidParameterExcetion(const ArithmeticExcption &e) : Exception(e) { }

    InvalidParameterExcetion &operator= (const ArithmeticExcption &e)
    {
        Exception::operator=(e);

        return *this;
    }
    ~InvalidParameterExcetion() override { }
};

}

#endif // EXCEPTION_H

文件:Exception.cpp

#include "Exception.h"

#include <cstring>
#include <cstdlib>

namespace DTLib
{

Exception::Exception(const char *message) : Exception(message, nullptr, 0)
{
}

Exception::Exception(const char *file, int line) : Exception(nullptr, file, line)
{
}

Exception::Exception(const char *message, const char *file, int line)
{
    m_message = strdup(message);

    if (file != nullptr)
    {
        char sl[16] = {0};

        itoa(line, sl, 10);

        m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
        m_location = strcpy(m_location, file);
        m_location = strcat(m_location, ":");
        m_location = strcat(m_location, sl);
    }
    else
    {
        m_location = nullptr;
    }
}

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()
{
    delete m_message;
    delete m_location;
}

}

文件:main.cpp

catch (const ArithmeticExcption &e)
TEST
..\DTLib\main.cpp:13

设计原则

在可复用代码库设计时,尽量使用面向对象技术进行架构,尽量使用异常处理机制分离正常逻辑和异常逻辑。

小结

  • 现在C++库必要包含充要的异常类族
  • 所有库中的数据结构都依赖于异常机制
  • 异常机制能够分离库中代码的正常逻辑和异常逻辑

以上内容整理于狄泰软件学院系列课程,请大家保护原创!

发表评论

0/200
86 点赞
0 评论
收藏
为你推荐 换一批