一、儘可能使用單繼承的方式進行系統設計(單繼承+多個接口的方式)ios
二、儘可能保持系統中只存在單一繼承樹(建立一個頂層的抽象父類)c++
三、儘可能使用組合關係代替繼承關係(後面會講)數據結構
不幸的事實架構
(1)、c++語言的靈活性使得代碼中能夠存放多個繼承樹ide
(2)、c++編譯器的差別使得一樣的代碼可能表現不一樣的行爲函數
如:new不成功的時候,之前的編譯器都會是返回一個空指針,可是如今通常都會拋出一個異常,不一樣的編譯器拋出的異常可能不同,這就會使得移植性大大下降測試
建立DTLib::Object類的意義spa
(1)、遵循經典設計準則,全部的數據結構都繼承自Object類設計
(2)、定義動態內存申請的行爲,提升代碼的移植性指針
一、頭文件
#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
值得注意的是,重載new時函數聲明後面都加上了 throw() ,表面new不成功不會拋出任何類型的異常。而將虛函數聲明爲純虛函數的意義在於使其子類都用於虛函數表,能進行動態類型識別。
二、實現文件
#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() { } }
要注意做爲純虛函數的析構函數也要進行定義(那些打印語句只是爲了測試方便)
三、測試
#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; }
經過輸出的結果能夠看出,new一個對象時使用了咱們重載的版本,同時也含有了指向虛函數表的指針。
(1)、Object類是DTLib中數據結構類的頂層父類
(2)、Object類用於統一動態內存申請的行爲
(3)、在堆中建立Object子類的對象,失敗時返回NULL值
(4)、Object類爲純虛父類,全部子類都能進行動態類型識別