C++数据结构第13课、类族结构的进化

  • 遵循经典设计准则
    在这里插入图片描述
  • 改进的关键点
    Exception 类继承自 Object
       堆空间中创建异常对象失败后,返回NULL指针
       
    — 新增 InvalidOperationException 异常类
       成员函数调用时,如果状态不正确则抛出异常
       
    SmartPointer 类继承自 Object 类
       堆空间中创建智能指针对象失败后,返回NULL指针
  • DTLib的开发方式和注意事项
    — 迭代开发
       每次完成一个小的目标,持续开发,最终打造可复用类库
       
    — 单一继承树
       所有的类都继承于Object,规范堆对象创建的行为
       
    只抛异常,不处理异常
       使用 THROW_EXCEPTION 抛出异常,提高可移植性。
       因为可能项目里面不支持异常处理,我们选择把宏定义后面那部分给注释掉,使得我们的代码依旧照常运行,这时候觉得一开始把抛出异常设置成宏定义真是神来之笔。
       
    — 弱耦合性
       尽量不使用标准库中的类和函数,提高可移植性

SmartPointer.h

#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H

#include "Object.h"
namespace DTLib
{

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

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

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

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

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

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

    T* get()
    {
        return m_pointer;
    }

    ~SmartPointer()
    {
        delete m_pointer;
    }
};
}
#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
{
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() = 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& 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 NoEnoughMemoryException : public Exception
{
public:
    NoEnoughMemoryException() : Exception(0){}
    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;
    }
};

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& e) : Exception(e){}
    InvalidParameterException& operator=(const InvalidParameterException& e)
    {
        Exception::operator=(e);
        return *this;
    }
};

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

    InvalidOperatorException(const InvalidOperatorException& e) : Exception(e){}
    InvalidOperatorException& operator=(const InvalidOperatorException& e)
    {
        Exception::operator=(e);
        return *this;
    }
};
}

#endif // EXCEPTION_H

Object.h

#ifndef OBJECT_H
#define OBJECT_H


namespace DTLib
{

class Object
{
public:
    void* operator new(unsigned int size)throw();

    void operator delete(void* p);

    void* operator new[](unsigned int size)throw();

    void operator delete[](void* p);

    virtual ~Object() = 0;
};
}

#endif // OBJECT_H

Exception.cpp

#include "Exception.h"
#include <cstring>
#include <cstdlib>

namespace DTLib
{

void Exception::init(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 = reinterpret_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
        if(m_location != nullptr)
        {
            strcpy(m_location, file);
            strcat(m_location, ":");
            strcat(m_location, sl);
        }

/*
13课的11min说明了原因      
下面这个不要抛出异常。逻辑上看:父类里面抛出了一个子类的对象作为异常,就很奇怪。老爸还没诞生,先将儿子扔出去?
                  代码上看:子类里面会调用父类的构造函数,就会形成死循环。
*/

//        else
//        {
//            THROW_EXCEPTION(NoEnoughMemoryException, "Exception::init");
//        }
    }
    else
    {
        m_location = nullptr;
    }
    }
}

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

Exception::Exception(const char* file, int line)
{
    init(nullptr, 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);
}

}

Object.cpp

#include "Object.h"

#include <iostream>
#include <cstdlib>
using namespace std;

namespace DTLib
{
void* Object::operator new(unsigned int size)throw()
{
    cout << "Object::operator new: " << size  << endl;
    return malloc(size);
}

void Object::operator delete(void* p)
{
    cout << "Object::operator delete: " << p  << endl;
    free(p);
}

void* Object::operator new[](unsigned int size)throw()
{
    return malloc(size);
}

void Object::operator delete[](void* p)
{
    free(p);
}

Object::~Object()
{

}

}

main.cpp

#include <iostream>
#include "SmartPointer.h"
#include "Object.h"
#include "Exception.h"

using namespace std;
using namespace DTLib;

int main()
{
    SmartPointer<int>* pt = new SmartPointer<int>;
    delete pt;

    InvalidOperatorException* pi = new InvalidOperatorException;
    delete pi ;
    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值