【數據結構】13_類族結構的進化

遵循經典設計準則

  • DTLib 中的全部類位於單一的繼承樹

image.png

改進的關鍵點

  • Exception 類繼承自 Object算法

    • 堆空間中建立異常對象失敗時,返回NULL指針
  • 新增 InvalidOperationException 異常類編程

    • 成員函數調用時,若是狀態不正確則拋出異常
  • SmartPointer 類繼承自 Object 類數據結構

    • 堆空間中建立智能指針對象失敗時,返回NULL指針

編程實驗:類族結構的進化

文件:SmartPointer.hide

#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H

#include "Object.h"

namespace DTLib
{

template<typename T>
class SmartPointer : public Object  // 修改
{
public:
    SmartPointer(T *p = nullptr)
    {
        m_pointer = p;
    }

    SmartPointer(const SmartPointer &obj)
    {
        m_pointer = obj.m_pointer;
        const_cast<SmartPointer&>(obj).m_pointer = nullptr;
    }

    SmartPointer &operator= (const SmartPointer &obj)
    {
        if (this != &obj)
        {
            delete m_pointer;
            m_pointer = obj.m_pointer;
            const_cast<SmartPointer&>(obj).m_pointer = nullptr;
        }

        return *this;
    }

    T *operator-> ()
    {
        return m_pointer;
    }

    T &operator* ()
    {
        return *m_pointer;
    }

    bool isNull()
    {
        return (m_pointer == nullptr);
    }

    T *get()
    {
        return m_pointer;
    }

    ~SmartPointer()
    {
        delete m_pointer;
    }

protected:
    T *m_pointer = nullptr;
};

}

#endif // SMARTPOINTER_H

文件:Exception.h函數

#ifndef EXCEPTION_H
#define EXCEPTION_H

#include "Object.h"

namespace DTLib
{

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

class Exception : public Object  // 修改
{
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;

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

    NullPointerException &operator= (const NullPointerException &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 IndexOutOfBoundsException &e) : Exception(e) { }

    IndexOutOfBoundsException &operator= (const IndexOutOfBoundsException &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 NoEnoughMemoryException &e) : Exception(e) { }

    NoEnoughMemoryException &operator= (const NoEnoughMemoryException &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 InvalidParameterExcetion &e) : Exception(e) { }

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

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

class InvalidOpertionExcetion : public Exception  // 增長
{
public:
    InvalidOpertionExcetion() : Exception(nullptr) { }
    InvalidOpertionExcetion(const char *message) : Exception(message) { }
    InvalidOpertionExcetion(const char *file, int line) : Exception(file, line) { }
    InvalidOpertionExcetion(const char *message, const char *file, int line) : Exception(message, file, line) { }

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

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

        return *this;
    }
    ~InvalidOpertionExcetion() 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;
}

}
  • DTLib 的開發方式和注意事項this

    • 迭代開發spa

      • 每次完成一個小的目標,持續開發,最終打造可複用類庫
    • 單一繼承樹設計

      • 全部類都繼承自 Object,規範堆對象建立時的行爲
    • 只拋異常,不處理異常指針

      • 使用 THROW_EXCEPTION 拋出異常,提升可移植性
    • 弱耦合性

      • 儘可能不使用標準庫中的類和函數,提升可移植性

說明1:只拋異常,不處理異常
背景:有公司會明確規定不容許使用異常處理機制(throw,try,catch)
解決方案:

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

說明2:儘可能不使用標準庫中的內容
背景:有公司會明確規定不容許使用標準庫
解決方案:當前只在Object文件和Exception文件中使用了malloc,free, strlen, strdup等極少數庫函數,這是極其容易被替換的。

第一階段學習總結

  • 數據結構與算法之間的關係
  • 算法效率的度量方法
  • DTLib 的基礎設施構建

    • 頂層父類
    • 智能指針
    • 異常類

以上內容整理於狄泰軟件學院系列課程,請你們保護原創!

相關文章
相關標籤/搜索