在當(dāng)代的軟件架構(gòu)實踐中,我們有三條準(zhǔn)則:1、盡量使用單重繼承的方式進行系統(tǒng)設(shè)計;2、盡量保持系統(tǒng)中只存在單一的繼承樹;3、盡量使用組合關(guān)系代替繼承關(guān)系。但是由于 C++ 語言的靈活性使得代碼中可以存在多個繼承樹,C++ 編譯器的差異使得同樣的代碼可能表現(xiàn)不同的行為。

我們想下,new 操作如果失敗將會發(fā)生什么呢?那么肯定會導(dǎo)致異常嘛,這時我們便用到了前面構(gòu)建的異常類,此時我們只需拋出一個內(nèi)存不足的異常,便會得到一個提示。我們這時便有必要來創(chuàng)建一個頂層的父類了,那么創(chuàng)建它的意義在哪呢?一是遵循經(jīng)典設(shè)計準(zhǔn)則,所有的數(shù)據(jù)結(jié)構(gòu)都繼承自 Object 類,二是定義動態(tài)內(nèi)存申請的行為,提高代碼的移植性。下面我們來看看頂層父類的接口定義,如下所示
class Object
{
public:
void* operator new (unsigned int size) throw();
void operator delete (void* p);
void* operator new[] (unigned int size) throw();
void operator delete[] (void* p);
virtual ~Object() = 0;
};下來我們還是以代碼為例來進行實驗
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_HObject.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()
{
return malloc(sizeof(size));
}
void Object::operator delete[] (void* p)
{
free(p);
}
Object::~Object()
{
}
}main.cpp 源碼
#include <iostream>
#include "Object.h"
using namespace std;
using namespace DTLib;
class Test : public Object
{
public:
int i;
int j;
};
class Child : public Test
{
public:
int k;
};
int main()
{
Object* obj1 = new Test();
Object* obj2 = new Child();
cout << "obj1 = " << obj1 << endl;
cout << "obj2 = " << obj2 << endl;
delete obj1;
delete obj2;
return 0;
}我們來看看編譯后的結(jié)果

我們看到在 main 函數(shù)中我們用 Object 父類的指針來創(chuàng)建了一個 Test 子類對象和 Child 子類對象。并且在創(chuàng)建對象的時候打印了 Object::operator new ,這很明顯就是調(diào)用了我們自己指定的 malloc 方式。為什么 Test 對象打印的是 12 呢?因為它里面包含了兩個 public 成員變量(int),再加上一個指向虛函數(shù)表的指針,一共是 12 個字節(jié)。底下的 Child 子類的分析是一樣的。在析構(gòu)的時候我們看到析構(gòu)時也打印出了我們寫的 Object::operator delete ,由此可以看出它的析構(gòu)也是調(diào)用的是我們自己定義的。
下來我們來看看經(jīng)典設(shè)計準(zhǔn)則是怎樣的,如下,我們自己的 DTLib 中華的所有類是位于單一的繼承樹的

我們再基于上面創(chuàng)建的頂層父類來改善下我們之前寫的異常類和智能指針(在 C++ 中有介紹過)。
1、Exception 類繼承自 Object 類。即堆空間中創(chuàng)建異常對象失敗時返回 NULL 指針
2、新增 InvalidOperationException 異常類。在成員函數(shù)調(diào)用時,如果狀態(tài)不正常則拋出異常類
3、SmartPointer 類繼承自 Object 類。在堆空間中創(chuàng)建智能指針對象失敗時返回 NULL 指針
下來我們還是以代碼為例來進行說明
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
{
private:
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();
};
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 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 InvalidParameterException& e)
{
Exception::operator =(e);
return *this;
}
};
}
#endif // EXCEPTION_HException.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 = (message ? strdup(message) : NULL);
if( file != NULL )
{
char s1[16] = {0};
itoa(line, s1, 10);
m_location = static_cast<char*>(malloc(strlen(file) + strlen(s1) + 2));
m_location = strcpy(m_location, file);
m_location = strcat(m_location, ":");
m_location = strcat(m_location, s1);
}
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 = e.m_message;
m_location = e.m_location;
}
Exception& Exception::operator= (const Exception& e)
{
if( this != &e )
{
free(m_message);
free(m_location);
m_message = e.m_message;
m_location = 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);
}
}SmartPointer.h 源碼
#ifndef SMARTPOINTER_
H#define SMARTPOINTER_H
#include "Object.h"
namespace DTLib
{
template < typename T >
class SmartPointer : public Object
{
private:
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_Hmain.cpp 源碼
#include <iostream>
#include "SmartPointer.h"
#include "Exception.h"
using namespace std;
using namespace DTLib;
int main()
{
SmartPointer<int>* p = new SmartPointer<int>();
delete p;
INvalidOPerationException* e = new INvalidOPerationException();
delete e;
return 0;
}我們在 Object 頂層父類中的 new 和 delete 函數(shù)中搭上斷點,同時也在 main 函數(shù)中的 SmartPointer 和 INvalidOPerationException 的 new 和 delete 操作中打上斷點,看看程序的執(zhí)行流,如下


第一幅圖是執(zhí)行 SmartPointer 指針的 new 和 delete 操作時輸出的信息,第二幅圖是執(zhí)行 INvalidOPerationException 指針的 new 和 delete 操作時輸出的信息。我們可以看到調(diào)用的 new 和 delete 操作都是 Object 中的函數(shù)。也就是說,我們現(xiàn)在的所有操作都是基于 Object 頂層父類的,由它統(tǒng)一 new 和 delete 的行為操作。我哦們在進行 DTLib 庫的開發(fā)時需要注意:1、迭代 開發(fā):也就是每次完成一個小目標(biāo),持續(xù)開發(fā),最終打造可復(fù)用類庫;2、單一繼承樹:所有樹都繼承自 Object,規(guī)范堆對象創(chuàng)建時的行為;3、只拋異常,不處理異常:使用 THROW_EXCEPTION 拋出異常,提高可移植性;4、弱耦合性:盡量不適應(yīng)標(biāo)準(zhǔn)庫中的類和函數(shù),提高可移植性。通過今天的學(xué)習(xí),總結(jié)如下:1、Object 類是 DTLib 庫中數(shù)據(jù)結(jié)構(gòu)類的頂層父類;2、Object 類用于統(tǒng)一動態(tài)內(nèi)存申請的行為;3、在堆中創(chuàng)建 Object 子類的對象,失敗時返回 NULL 值;4、
Object 類為純虛父類,所有子類都能進行動態(tài)類型識別。至此我們的庫的基礎(chǔ)設(shè)施構(gòu)建基本已經(jīng)完成:頂層父類、智能指針、異常類。
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
網(wǎng)站名稱:頂層父類的構(gòu)建(五)-創(chuàng)新互聯(lián)
本文URL:http://www.chinadenli.net/article40/dgejeo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、電子商務(wù)、外貿(mào)網(wǎng)站建設(shè)、靜態(tài)網(wǎng)站、Google、小程序開發(fā)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容