GeekBand C++面向?qū)ο蟾呒?jí)編程(上) Thrid Week
面向?qū)ο缶幊?Object Oriented Progamming)
Inheritance (繼承)
繼承表示一種 ‘is-a' 的關(guān)系辽社。有基類(base class) 和 派生類(derived class)。 繼承分為單個(gè)繼承和多重繼承,同時(shí)繼承的訪問(wèn)權(quán)限也有public,private会油,protected(默認(rèn)是private)地消。
class Shape
{
public:
Shape() {}
virtual ~Shape() {}
private:
int no_;
};
class Rectangle: public Shape
{
public:
Rectangle() {}
virtual ~Rectangle() {}
private:
int x_;
int y_;
};
Rectangle 繼承自 Shape,Rectangle可以訪問(wèn)基類的成員函數(shù)徽龟。
繼承關(guān)系的構(gòu)造函數(shù)是由內(nèi)而外贤旷,子類的構(gòu)造函數(shù)先調(diào)用基類的默認(rèn)構(gòu)造函數(shù)广料,然后才執(zhí)行自己。
Rectangle::Rectangle(...): Shape() {...} // Shape() 是編譯器附加的代碼
析構(gòu)函數(shù)是由外而內(nèi)幼驶,子類的析構(gòu)函數(shù)首先執(zhí)行自己艾杏,然后才調(diào)用基類的析構(gòu)函數(shù)。
Rectangle::~Rectangle(...) { ... ~Shape() } // ~Shape() 是編譯器附加的代碼
base class 的 析構(gòu)函數(shù)必須寫(xiě)成virtual盅藻,否則在以下情況會(huì)出現(xiàn)部分析構(gòu)的情況(表現(xiàn)為 undifined behavior)购桑。
Shape* ps = new Rectangle();
delete ps; // 這種情況下如果基類的析構(gòu)函數(shù)不是virtual,只能執(zhí)行基類的析構(gòu)函數(shù)氏淑,而子類的部分不能析構(gòu)勃蜘。
繼承中的虛函數(shù):
- non-virtual 函數(shù): 不希望子類重寫(xiě)(override)
- virtual 函數(shù): 希望派生類重寫(xiě)它,如果派生類沒(méi)有重寫(xiě)假残,可以使用基類的默認(rèn)定義版本
- pure-virtual 函數(shù): 派生類一定要重新定義缭贡。 定義了純虛函數(shù)則該類被認(rèn)為為抽象類。
Composition (復(fù)合)
復(fù)合是一種表示 'has-a' 的關(guān)系辉懒。一個(gè)類中包含了另一個(gè)類的實(shí)例阳惹。
class StringRep;
class String {
public:
String();
String(const String&s)
String &operator=(const Stirng&s);
~String();
private:
StringRep rep;
};
復(fù)合方式的構(gòu)造函數(shù)由內(nèi)而外,Container的構(gòu)造函數(shù)首先調(diào)用Component的defaul構(gòu)造函數(shù)耗帕,然后才執(zhí)行自己穆端。
Container::Container(...):Component() {...};
析構(gòu)的時(shí)候是由外而內(nèi),Container的析構(gòu)函數(shù)首先執(zhí)行自己仿便,然后才調(diào)用Component的析構(gòu)函數(shù)。
Container::~Container(...) {... ~Component() };
Delegation (委托)
委托 是一種以指針?lè)绞降膹?fù)合攒巍。一個(gè)類中包含了另一個(gè)類的指針嗽仪。
class StringRep;
class String {
public:
String();
String(const String&s)
String &operator=(const Stirng&s);
~String();
private:
StringRep* rep;
};
面向?qū)ο蟮脑O(shè)計(jì)模式 (Object Oriented Design)
Template Method
模版方法 是預(yù)先定義好操作的骨架,預(yù)留一些步驟的實(shí)現(xiàn)給子類柒莉。
C++ 中繼承中的虛函數(shù)即可完成這樣的功能闻坚。
CDocument::OnFileOpen()
{
...
Serialize();
...
}
class CMyDoc:public CDocumment
{
virtual Serialize() {...}
}
Observer
觀察者模式,是定義一種一對(duì)多的依賴關(guān)系兢孝,當(dāng)這這其中的一個(gè)改變時(shí)窿凤,所有其它依賴的對(duì)象都能自動(dòng)的被通知和更新仅偎。
在C++ 中可以使用 Delegation+Inheritance 實(shí)現(xiàn)。
class Subject
{
int m_value;
vector<Observer*> m_views;
public:
void attach(Observer* obs)
{
m_views.push_back(obs);
}
void set_val(int value)
{
m_value = value;
notify();
}
void notify()
{
for(int i = 0; i < m_views.size(); ++i)
{
m_views[i]->update(this, m_value);
}
}
};
class Observer
{
public:
virtual void update(Subject* sub, int value) = 0;
};
class Observer1: public Observer
{
void update(int v)
{
...
}
};
class Observer2: public Observer
{
void update(int v)
{
...
}
};
Composite
Composite的典型例子就是文件系統(tǒng)雳殊。文件系統(tǒng)由目錄和文件組成橘沥。每個(gè)目錄都可以裝內(nèi)容。目錄的內(nèi)容可以是文件夯秃,也可以是目錄座咆。按照這種方式,計(jì)算機(jī)的文件系統(tǒng)就是以遞歸結(jié)構(gòu)來(lái)組織的仓洼。如果你想要描述這樣的數(shù)據(jù)結(jié)構(gòu)介陶,那么你可以使用組合模式Composite。
C++ 中可以通過(guò) Delegation+I(xiàn)nheritance 實(shí)現(xiàn)
class Componet
{
int value;
public:
Componet(int val) {value = val;}
virtual void add(Component*) {}
};
class Composite:public Component
{
vector<Component*> c;
public:
Composite(int val):Component(val) {}
void add(Component* elem) {
c.push_back(elem);
}
};
class Leaf:public Component
{
public:
Leaf(int val):Component(val) {}
};