zoukankan      html  css  js  c++  java
  • 第十三课、类族的结构进化-------------------狄泰软件学院

    一、遵循经典设计原则

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

    IvalidOperationEXception是新增的异常类,描述某些成员函数在状态不对的时候被抛出

    二、改进的关键点

    1、EXception类继承自Object类:堆空间中创建异常对象失败时,返回NULL指针,用的是自己的new版本

    更改:

    2、新增IvalidOperationEXception异常类:成员函数调用时,如果状态不正确则抛出该异常

    增加:

    //非法操作异常
    class IvalidOperationEXception:public Exception
    {
    public:
        IvalidOperationEXception():Exception(0) {}
        IvalidOperationEXception(const char* message):Exception(message) {}
        IvalidOperationEXception(const char* file, int line):Exception(file, line) {}
        IvalidOperationEXception(const char* message, const char* file, int line):Exception(message, file, line) {}
        IvalidOperationEXception(const IvalidOperationEXception& e): Exception(e) {}
        IvalidOperationEXception& operator = (const IvalidOperationEXception& e)
        {
            Exception::operator =(e);
            return *this;
        }
    };

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

    更改:

    注:前面课程的代码还有一些不完美

    在EXception.cpp中修改init()函数,判断申请内存是否成功

    void Exception::init(const char* message, const char* file, int line)
    {
        m_message = strdup(message);//指向的message可能在栈空间,也可能在堆空间或者全局数据去,
                                    //为了安全,这里先复制一份到堆空间
    
        if( file != NULL)
        {
            char sl[16] = {0};
            itoa(line, sl, 10);//首先将行号转化为字符串
    
            m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
    
            if( m_location !=NULL )
            {
                m_location = strcat(m_location, file);
                m_location = strcat(m_location, ":");
                m_location = strcat(m_location, sl);
            }
    
        }
        else
        {
            m_location = NULL;
        }
    }

    但是一定要注意判断语句的else分支中不能抛出内存不足的异常,原因可以从下面两个方面分析

    (1)、站在一个高的角度看,内存不足的异常类是继承自抽象的异常父类,老爸还没存生就抛出儿子肯定是非法的

    (2)、站在代码的角度看,构建对象的会先调用父类的构造函数,肯定又会进入到init()函数,最终会造成死循环

    所以说最好的办法就是省去else语句。

    三、第一阶段完整代码

    #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
    Object.h
    #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()
    {
        cout << "Object::operator new[]" << endl;
        return malloc(size);
    }
    
    void Object::operator delete[] (void* p)
    {
        cout << "Object::operator delete[]" << endl;
        free(p);
    }
    
    Object::~Object()
    {
    
    }
    
    }
    Object.cpp
    #ifndef SMARTPOINTER_H
    #define SMARTPOINTER_H
    #include "Object.h"
    
    namespace DTLib
    {
    template <typename T>
    class SmartPoiter : public Object
    {
    protected:
        T* m_pointer;
    public:
        SmartPoiter(T* p = NULL)
        {
            m_pointer = p;
        }
    
        SmartPoiter(const SmartPoiter<T>& obj)
        {
            m_pointer = obj.m_pointer;
            const_cast<SmartPoiter<T>&>(obj).m_pointer = NULL;
        }
    
        SmartPoiter<T>& operator = (const SmartPoiter<T>& obj)
        {
            if( this != &obj )
            {
                delete m_pointer;
                m_pointer = obj.m_pointer;
                const_cast<SmartPoiter<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;
        }
    
        ~SmartPoiter()
        {
            delete m_pointer;
        }
    };
    }
    
    #endif // SMARTPOINTER_H
    SmartPoiter.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 IvalidOperationEXception:public Exception
    {
    public:
        IvalidOperationEXception():Exception(0) {}
        IvalidOperationEXception(const char* message):Exception(message) {}
        IvalidOperationEXception(const char* file, int line):Exception(file, line) {}
        IvalidOperationEXception(const char* message, const char* file, int line):Exception(message, file, line) {}
        IvalidOperationEXception(const IvalidOperationEXception& e): Exception(e) {}
        IvalidOperationEXception& operator = (const IvalidOperationEXception& e)
        {
            Exception::operator =(e);
            return *this;
        }
    };
    
    }
    
    #endif // EXCEPTION_H
    Exception.h
    #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可能在栈空间,也可能在堆空间或者全局数据去,
                                    //为了安全,这里先复制一份到堆空间
    
        if( file != NULL)
        {
            char sl[16] = {0};
            itoa(line, sl, 10);//首先将行号转化为字符串
    
            m_location = static_cast<char*>(malloc(strlen(file) + strlen(sl) + 2));
    
            if( m_location !=NULL )
            {
                m_location = strcat(m_location, file);
                m_location = strcat(m_location, ":");
                m_location = strcat(m_location, sl);
            }
    
        }
        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);
    }
    
    }
    Exception.cpp
    #include <iostream>
    #include "Object.h"
    #include "Exception.h"
    #include "SmartPointer.h"
    
    using namespace std;
    using namespace DTLib;
    
    
    
    int main()
    {
        IvalidOperationEXception* p = new IvalidOperationEXception();
        delete p;
    
        SmartPoiter<int>* s = new SmartPoiter<int>();
        delete s;
    
    
        return 0;
    }
    main.cpp

    四、DTLib的开发方式和注意事项

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

    2、单一继承树:所有类都继承自Object,规范堆空间创建时的行为

    3、只抛异常,不处理异常:使用THROW_EXCEPTION抛出的异常,提高可移植性

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

    注:在一些老编译器中,可能不支持异常处理,我们可以将宏

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

    修改为

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

    这样,抛出异常的语句就形同虚设了,相当于没有抛出一样,增加了可移植性。

    五、第一阶段学习总结

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

    2、算法效率的度量方法

    3、DTLib的基础设施

    (1)、顶层父类

    (2)、智能指针

    (3)、异常类

  • 相关阅读:
    DotNet的JSON序列化与反序列化
    DotNet指定文件显示的尺寸
    将文本文件的内容存储在DataSet中的方法总结
    Apple的LZF算法解析
    DotNet常用排序算法总结
    C#创建安全的字典(Dictionary)存储结构
    C#创建安全的栈(Stack)存储结构
    转化代码:添加在您网页中用户触发转化行为之后的地方。添加方法
    nginx配置ThinkPHP5二级目录访问
    好久没写原生的PHP调用数据库代码了分享个
  • 原文地址:https://www.cnblogs.com/gui-lin/p/6827896.html
Copyright © 2011-2022 走看看