zoukankan      html  css  js  c++  java
  • 第13课 类族结构的进化

    1. 遵循经典设计准则

    (1)DTLib中所有类位于单一的继承树

     

    (2)改进的关键点

      ①Exception类继承自Object类:堆空间中创建异常对象失败时,返回NULL指针。

      ②新增InvalidOperationException类:成员函数调用时,如果状态不正确则抛出异常。

      ③SmartPointer类继承自Object类:堆空间中创建智能指针对象失败时,返回NULL指针。

    2. DTLib的开发方式和注意事项

    (1)迭代开发:每次完成一个小的目标,持续开发,最终打造可复用类库

    (2)单一继承树:所有类都继承自Object,规范堆对象创建时的行为

    (3)只抛异常,不处理异常:使用THROW_EXCEPTION抛出异常,提高可移植性。这样就可以比较方便地将代码移植到老的编译器,所要做的工作只需将THROW_EXCEPTION宏后半部分注释掉,即#define THROW_EXCEPTION(e, m) //(throw e(m, __FILE__, __LINE__)))。同时由于DTLib库只抛异常,而不处理异常这意味着库中无需使用try-catch语句因此就可以把异常相关的处理从DTLib中剔除,让使用库的人自己去处理异常,从而提高了代码的可移植性

    (4)弱耦合性:尽量不使用标准库中的类和函数,提高可移植性。

    【编程实验】类族结构的进化

    //Object.h

    #ifndef _OBJECT_H_
    #define _OBJECT_H_
    
    namespace DTLib
    {
    
    class Object
    {
    public:
        //以下四个重载函数用于统一不同编译器new失败时的结果不同的问题。
        //throw()表示不抛出异常,即如果申请内请失败时,统一返回NULL而不抛异常
        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_

    //Object.cpp

    #include "Object.h"
    #include <cstdlib>
    #include <iostream>
    
    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()
    {
        //当用new Test[5]时,只须传入数组元素的个数,编译器会向operator new[](...)函数的参数
        //传入5*sizeof(Test) + sizeof(unsigned int),其中的sizeof(unsigned int)为额外
        //空间,用于保存元素的个数。
        cout <<"Object::operator new[]: " << size << endl;
        return malloc(size);
    }
    
    void Object::operator delete[](void *p)
    {
        cout <<"Object::operator delete[]: " << p << endl;
        free(p);
    }
    
    Object::~Object()
    {
    
    }
    
    }

    //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 = NULL)
        {
            m_pointer = p;
        }
    
        //拷贝构造函数
        SmartPointer(const SmartPointer<T>& obj)
        {
            m_pointer = obj.m_pointer;
    
            //所有权转移,使得同一时刻只能由一个指针指向堆空间
            const_cast<SmartPointer<T>&>(obj).m_pointer = NULL;
        }
    
        //重载赋值操作符
        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 = NULL;
            }
            return *this;
        }
    
        //重载->操作符
        T* operator->()
        {
            return m_pointer;
        }
    
        //重载*操作符
        T& operator*()
        {
            return *m_pointer;
        }
    
        bool isNull()
        {
            return (m_pointer == NULL);
        }
    
        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;
    
        //注意:
        //(1)析构函数是较为特殊的函数,一旦定义了析构函数,不管这个函数是不是纯虚函数,就
        //必须提供实现。因为,对象在销毁时,最后都会调用父类的析构函数。如果父类不提供实现,
        //当对象销毁过程中调用到父类析构函数时,就找不到析构函数,也就不知该如何析构下去。
        //因此,尽管这里将析构函数声明为纯虚函数,但Exception类仍提供析构函数的实现。以便
        //最后正确释放掉m_message和m_location所指的堆空间.
        //(2)此外,声明为纯虚函数,可以让该类只能作为接口使用,而且也强迫子类必须
        //提供析构函数的实现。
        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 NotEnoughMemoryException: public Exception
    {
    public:
        NotEnoughMemoryException():Exception(0){}
        NotEnoughMemoryException(const char* message):Exception(message){}
        NotEnoughMemoryException(const char*file, int line):Exception(file, line){}
        NotEnoughMemoryException(const char *message, const char* file, int line):Exception(message, file, line){}
    
        NotEnoughMemoryException(const NotEnoughMemoryException& e): Exception(e){}
        NotEnoughMemoryException& operator=(const NotEnoughMemoryException& 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 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& e): Exception(e){}
        InvalidOperationException& operator=(const InvalidOperationException& e)
        {
            Exception::operator =(e);
    
            return *this;
        }
    };
    
    }
    
    #endif // _EXCEPTION_H_

    //Exception.cpp

    #include "Exception.h"
    #include <cstring>
    #include <cstdlib>
    
    using namespace std;
    
    namespace DTLib
    {
    
    void Exception::init(const char *message, const char *file, int line)
    {
        m_message = strdup(message); //复制message的内容
    
        m_location = NULL;
    
        if(file != NULL){
            char sl[16]={0};
            itoa(line, sl, 10);//将整数line转为字符串,其中的10表示转换为十进制格式
    
            //m_location的格式为:file:line;
            m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
    
            //注意:申请内存失败时无须再抛NotEnoughMemoryException异常,从宏观上看,父类
            //是无法抛出子类型的异常的。从逻辑上看也不能抛出这个异常,因为当父类构造时出现异常时,
            //如果去抛出子类异常,则必然需要构造子类,但这又得先调用父类构造函数(会再一次产
            //生异常,从而造成Exception构造函数的递归调用,从而造成死循环!)
            if(m_location != NULL){   //内存申请成功
                m_location = strcpy(m_location, file);
                m_location = strcat(m_location, ":");
                m_location = strcat(m_location, sl);
            }
        }
    }
    
    //构造函数
    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>
    #include "SmartPointer.h"
    #include "Exception.h"
    
    using namespace std;
    using namespace DTLib;
    
    int main()
    {
        SmartPointer<int>* sp = new SmartPointer<int>();
    
        delete sp;
    
        InvalidOperationException* e = new InvalidOperationException();
    
        delete e;
    
        return 0;
    }
    /*输出结果
    Object::operator new: 8
    Object::operator delete: 0x7a12a8
    Object::operator new: 12
    Object::operator delete: 0x7a12a8
    */

    3. 第一阶段学习总结

    (1)数据结构与算法之间的关系

    (2)算法效率的度量方法

    (3)DTLib的基础设施构建:顶层父类、智能指针、异常类…

  • 相关阅读:
    leetcode-5-Longest Palindromic Substring
    leetcode-3-Longest Substring Without Repeating Characters
    leetcode-2-Add Two Numbers
    正则匹配-题型总结
    Kmp简单运用
    最长回文子串
    树-leetcode做题笔记
    java对象与类
    【LeetCode & 剑指offer刷题】查找与排序题13:Merge Intervals
    【LeetCode & 剑指offer刷题】查找与排序题12:Top K Frequent Elements
  • 原文地址:https://www.cnblogs.com/5iedu/p/6754813.html
Copyright © 2011-2022 走看看