GeekBandC++開(kāi)發(fā)工程師第三周學(xué)習(xí)筆記

類與類之間有三大關(guān)系:繼承(Inheritance)、復(fù)合(Composition)和委托(Delegation)

3.1.1 復(fù)合(Composition)

template <class T, class Sequence = deque <T> >

class queue {

? . . .

protected:

? ? ?Sequence c;

public:

? ? ? bool empty() const { return c.empty(); }

? ? ? size_type size() const? { return s.size(); }

? ? ? reference front() { return c.front(); }

? ? ? reference back() { return c.back(); }

? ? ? void push(const value_type& x) {c.push_back(x);}

? ? ? void pop() { c.pop_front(); }

};

3.1.2(Adapter:)改造

//No:1

template?

class?queue{

...

protected?c;//擁有模塊2

...

};

//No:2

template?

class?queue{

protected:

Itr?strat;//擁有模塊3,sizeof:16

Itr?finish;

T**?map;//指針的指針,4個(gè)字節(jié)

unsigned?int?map_size;//4個(gè)字節(jié)

};

//No:3

template?

struct?Itr{

T*?cur;//sizeof:4*4

T*?first;

T* last;

T**?node;

...

};

3.1.3復(fù)合關(guān)系下的構(gòu)造函數(shù)和析構(gòu)函數(shù):

構(gòu)造由內(nèi)而外:Container::Component(...): Component() {...};

Container的構(gòu)造函數(shù)首先調(diào)用Component的default構(gòu)造然后才執(zhí)行自己

析構(gòu)由外而內(nèi):Container :: ~Container(...) { ... ~Component() }

Container的析構(gòu)函數(shù)首先執(zhí)行自己,然后才調(diào)用Component的析構(gòu)函數(shù)

3.2 委托:兩個(gè)類之間相連

class?String{

public:

String();

~String();

String(const?char*s);

String(const?String&?a);

String?&operator=(const?String&?s);

private:

StringRep*?rep;//等到需要用到StringRep時(shí)才去創(chuàng)建StringRep類

};

class?StringRep{

friend?class?String;

StringRep(const?char*?s);

~StringRep();

int?count;

char*?rep;

}

3.3.1 繼承:

struct?_List_node_base

{

_List_node_base*?_M_next:

_List_node_base*?_M_prev;

};

template

struct?_List_node?:public?_List_node_base

{

_Tp ? _M_data;//它除了擁有自己的東西以外,還擁有基類的兩個(gè)東西

};

3.3.2基類的析構(gòu)函數(shù)必須是virtual,否則會(huì)出現(xiàn)undefined behavior

在繼承的情況下,構(gòu)造由內(nèi)而外:Derived::Derived(...) : Base() {...};

Derived的構(gòu)造函數(shù)首先調(diào)用基類的默認(rèn)構(gòu)造函數(shù),然后才執(zhí)行自己

析構(gòu)由外而內(nèi):Derived的析構(gòu)函數(shù)首先執(zhí)行自己,然后才調(diào)用基類的析構(gòu)函數(shù)

Derived::~Derived(...){... ~Base() };

3.3.3

non-virtual函數(shù):你不希望derived class 重新定義它

virtual函數(shù):你希望derived class重新定義它,且它已有默認(rèn)定義。

pure virtual函數(shù):你希望derived class一定要重新定義它,你對(duì)他沒(méi)有默認(rèn)定義。

3.4?純虛函數(shù):virtual 函數(shù)類型 函數(shù)名(參數(shù)表)=0;

聲明為純虛函數(shù)后,基類中就不再給出函數(shù)的實(shí)現(xiàn)部分,且純虛函數(shù)不具備函數(shù)的功能,不能被調(diào)用。

作用:在基類中為其派生類保留一個(gè)函數(shù)的名字。以便派生類根據(jù)需要對(duì)它進(jìn)行重載

3.5. ?inheritance+Composition關(guān)系下的構(gòu)造和析構(gòu):

派生類中有基類的part,但派生類中又有Component,這時(shí),調(diào)用順序是基類=Component.>派生類

派生類中有基類的part,而基類part中又有Component時(shí),這時(shí)調(diào)用順序?yàn)椋篊omponent>基類>派生類,析構(gòu)函數(shù)正好相反

委托+繼承:

class?Subject{

int?m_value;

vector?m_views;//容器里的類型為Observe*

public:

void?attach(Observe*?obs)

m_views.push_back(obs);

void?set_val(int?value)

{

m_value?=?value;

motify();

}

void?notify()

{

for(int?i=0;i

m_views[i]->update(this,m_value);

}

};

class?Observe{

public:

virtual?void?update(Subject*?sub,int?value)const?=0;

};

委托+繼承:

容器里面的東西一定要放一樣的大小,指針是最優(yōu)選

變量名:partname

#nclude

enum?imageType{LAST,SPOT};//枚舉

class?Image{

public:

virtual?void?draw()=0;

static?Image*?findAndClone(imageType);

protected:

virtual?imageType?return?Type()=0;

virtual?Image*?clone()?=0;//要求子類必須對(duì)其進(jìn)行編譯

static?void?assProtype(Image?*image)//靜態(tài)成員函數(shù)

{

_prototypes[_nextSlot++]

}

private:

static?Image*?__prototypes[10];

static?int?_nextSlot;//class當(dāng)中的靜態(tài)date,一定要在這個(gè)類外做一次定義,分配內(nèi)存

};

Image?*Image::_prototypes[];

int?Image::_nextSlot;

Image?*Image::findAndClone(imageType?type)

{//當(dāng)下面所有的子類把自己的一份原型放上去之后填充的數(shù)組

for(int?i=0;i<_nextSlot;i++)

{

if(_prototypes[i]->()?==type)//找到一個(gè)原型之后,調(diào)用clone(),就做了一個(gè)副本

return?_prototypes[i]->clone;

}


public繼承和is-a之間的等價(jià)關(guān)系聽(tīng)起來(lái)頗為簡(jiǎn)單,但有時(shí)候會(huì)誤導(dǎo)人

企鵝是一種鳥(niǎo),這是對(duì)的;鳥(niǎo)會(huì)飛,這也對(duì)的。但企鵝會(huì)飛嗎?

class Bird{

public:

virtual void fly();//鳥(niǎo)會(huì)飛

...

};

class Penguin:public Bird{//企鵝是一種鳥(niǎo)

...

};

這個(gè)代碼但是是行得通的,但是那不是真的。

上述例子中,有一個(gè)與事實(shí)不符的error。如果謹(jǐn)慎一點(diǎn),應(yīng)該是:有的鳥(niǎo)會(huì)飛,有點(diǎn)鳥(niǎo)不會(huì)飛。來(lái)塑模出較佳的真實(shí)性:

class Bird{

public:

...//沒(méi)有聲明fly()函數(shù)

};

class FlyingBird:public Bird{

public:

? ? ? virtual void fly();//鳥(niǎo)會(huì)飛

? ? ? ?...

};

class Penguin:public Bird{//企鵝是一種鳥(niǎo)

...

};

這樣的繼承體系才能比原先的設(shè)計(jì)更能忠實(shí)反映出真正的意思。

現(xiàn)在,如果非得要求企鵝會(huì)飛,那編譯器會(huì)不滿:

Penguin p;

p.fly();//錯(cuò)誤

一個(gè)好的接口可以防止無(wú)效的代碼通過(guò)編譯,因此應(yīng)該采取“在編譯期拒絕企鵝飛行”的設(shè)計(jì),而不是“只在運(yùn)行期間才能偵測(cè)它們”的設(shè)計(jì)。

所以,is-a并不是唯一存在于類之間的關(guān)系。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容