第三周
類之間的關(guān)系
面向?qū)ο蟮乃枷耄?/p>
- inheritance(繼承)
- composition(復(fù)合)
- Delegation(委托)
復(fù)合(has-a)
容器: queue:一端進一端出攀芯,deque:兩端進竞膳,兩端出
adapter:改造,適配:
對象適配器
將需要被適配的類的對象作為自己私有屬性伟桅,實現(xiàn)目標類的接口祠饺。
類適配器
繼承自需要被適配的類越驻,并且實現(xiàn)目標類的接口。
構(gòu)造函數(shù)和析構(gòu)函數(shù)
- 構(gòu)造由內(nèi)而外
Container的構(gòu)造函數(shù)先調(diào)用Component的默認構(gòu)造函數(shù)道偷,然后再執(zhí)行自己的缀旁,默認不符合要求時,需要自己寫勺鸦。
- 析構(gòu)函數(shù)由外而內(nèi)
Container的析構(gòu)函數(shù)首先執(zhí)行自己的并巍,然后再調(diào)用Component的析構(gòu)函數(shù)
委托(Delegation)Composition by reference
包含另一個類的指針
String中只有接口(Handle),StringRep中才是真正的實現(xiàn)(Body):(編譯防火墻)
class StringRep;
class String
{
public:
String();
String(const char * s);
String &operator=(const String& s);
~String();
private:
StringRep* rep; //pimpl
}
//file String.cpp
#include "String.hpp"
class StringRep
{
friend class String;
StringRep(const char* s);
~StringRep();
int count; //記錄拷貝一樣的次數(shù)换途。(共享一個StringRep)懊渡,copy on write(寫時給副本去寫)
char* rep;
}
優(yōu)點:接口對外不變刽射,內(nèi)部實現(xiàn)可以任意切換,不影響調(diào)用剃执。
繼承(is-a)
三種繼承方式:public誓禁,private,protected
虛函數(shù)和繼承結(jié)合使用
子類的對象中有父類的成分
構(gòu)造由內(nèi)而外
Derived的構(gòu)造函數(shù)先調(diào)用Base的default構(gòu)造函數(shù)肾档,然后再執(zhí)行自己的
析構(gòu)由外而內(nèi):
Derived的析構(gòu)函數(shù)首先執(zhí)行自己现横,然后在調(diào)用Base的析構(gòu)函數(shù)
Base的class的析構(gòu)函數(shù)必須是virtual,否則會出現(xiàn)undefined behavior
虛函數(shù)與多態(tài)
函數(shù)繼承的是調(diào)用權(quán)
三種:
- non-virtual函數(shù)阁最,不希望derived class重新定義(override)的
- virtual 希望derived class重新定義
- pure virtual 希望derived class一定要重新定義戒祠,此函數(shù)沒有默認定義(可以有定義)
class Shape
{
virtual void draw() const = 0; ///pure Virtual
virtual void error(const std::String & msg); ///impure virtual
int objectID() const; ///non-virtual
}
Template Method
通過子類對象調(diào)用父類函數(shù),當父類的是虛函數(shù)速种,并且子類重定義過姜盈,執(zhí)行子類的函數(shù)定義
功能最強大:
Delegate + inheritance
委托的相關(guān)設(shè)計
單數(shù)據(jù)源,多界面顯示
//數(shù)據(jù)class:
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(Subgect* sub馏颂,int value)= 0;
}
文件系統(tǒng):
//Composite
class Component //父類
{
int value;
public:
virtual void add(Component*){} //不能用純虛
};
class Primitive:public Component //單體(文件)
{
//繼承add棋傍,但是無實意
};
class Composite:public Component //組合
{
vector<Component*> vec; ///可以包含自己或者Primitive救拉;
void add(Component* elem)
{c.push_back(elem);}
};
樹狀繼承體系
Prototype:
#include<iostream>
enum imageType
{
LSAT,SPOT
};
class Image
{
public:
virtual void draw()=0;
static Image * find_AndClone(imageType);
protected:
virtual imageType returnType()=0;
virtual Image *clone()=0;
//As each subclass of Image is declared,it registers its prototype
statc void addPrototype(Image *image) ///添加子類到內(nèi)存
{
_prototypes[_nextSlot++] = image;
}
private:
//addPrototype() save each registered prototype here
static Image *_prototype[10];
static int _nextSlot;
};
Image *image::prototypes[]; ///定義
int Image::_nextSlot;
//client calls this public static member function when it need an instance
//of an Image subclass
Image *Image::findAndClone() ///外部調(diào)用
{
for(int i= 0;i < _nextSlot;i++)
if (prototype[i]->returnType()==type)
return _prototype[i]->clone();
}
class LandSatImage:public Image
{
public:
imageType returnType()
{
return LSAT;
}
void draw()
{
cout << "LandSatImage::draw" << _id << endl;
}
//When clone() is called,call the one-argument ctor with a dummy arg
Image *clone() ///復(fù)制本身
{return new LandStaImage(1);}
protected:
//This is only called from clone()
LandSatImage(int dummy)
{
_id = _count++; ///復(fù)制數(shù)量
}
priate:
//Mechanism for imitializing an Image subclass - this causes the
//default ctor to be called,which registers the subclass's prototype
static LandSatImage landSatImage;
//This is only called when the private static data member is inited
LandSatImage()
{
addPrototype(this); ///構(gòu)造函數(shù)里添加到父類
}
//Norminal 'state' per instance mechanism
int _id;
static int _count;
};
// Register the subclass's prototype
LandSatImage LandSatImage::_landSatImage;
//Initialize the "state" per instance mechanism
int LandSatImage::_cont = 1;
class SpotImage:public Image
{
public:
imageType returnType()
{
return SPOT;
}
void draw()
{
cout << "SpotImage::draw" << _id << endl;
}
Image *clone()
{
return new SpotImage(1);
}
protected:
SpotImage(int dummy)
{
_id = _count++;
}
private:
SpotImage()
{
addPrototype(this);
}
static SpotImage _spotImage;
int id;
static int _count;
};
SpotImage SpotImage::_spotImage;
int SpotImage::_count = 1;
//Simulated stream of creation requests
const int NUM_IMAGES = 8;
imageType input[NUM_IMAGES] =
{
LSAT,LSAT,LSAT,SPOT,LSAT,SPOT,SPOT,LSAT
};
int main()
{
Image *image[NUM_IMAGES];
//Given an image type,find the right prototype ,and return a clone
for(int i= 0; i < NUM_IMAGES;i++)
images[i] = Image::findAndClone(input[i]);
//Demeonstrate that correct image objects have been cloned
for(i = 0;i < NUM_IMAGES;i++)
images[i]->draw();
//Free the dynameic memory
for(i = 0;i < NUM_IMAGES;i++)
delete images[i];
}