第十三課、類族的結構進化-------------------狄泰軟件學院

1、遵循經典設計原則

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

IvalidOperationEXception是新增的異常類,描述某些成員函數在狀態不對的時候被拋出算法

2、改進的關鍵點

一、EXception類繼承自Object類:堆空間中建立異常對象失敗時,返回NULL指針,用的是本身的new版本安全

更改:數據結構

二、新增IvalidOperationEXception異常類:成員函數調用時,若是狀態不正確則拋出該異常ide

增長:函數

//非法操做異常
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; } };

三、SmartPointer類繼承自Object類:堆空間中建立智能指針對象失敗時,返回NULL指針學習

更改:this

注:前面課程的代碼還有一些不完美spa

在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語句。

3、第一階段完整代碼

#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

4、DTLib的開發方式和注意事項

一、迭代開發:每次完成一個小目標,持續開發,最終打造可複用類庫

二、單一繼承樹:全部類都繼承自Object,規範堆空間建立時的行爲

三、只拋異常,不處理異常:使用THROW_EXCEPTION拋出的異常,提升可移植性

四、若耦合性:儘可能不使用標準庫中的類和函數,提升可移植性

注:在一些老編譯器中,可能不支持異常處理,咱們能夠將宏

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

修改成

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

這樣,拋出異常的語句就形同虛設了,至關於沒有拋出同樣,增長了可移植性。

5、第一階段學習總結

一、數據結構與算法之間的關係

二、算法效率的度量方法

三、DTLib的基礎設施

(1)、頂層父類

(2)、智能指針

(3)、異常類

相關文章
相關標籤/搜索