- 继承 (Inheritance)
- 复合 (Composition)
- 委托 (Delegation)
继承
表示 is-a
struct _List_node_base
{
_List_node_base* _M_next;
_List_node_base* _M_prev;
};
template<typename _Tp>
struct _List_node: public _List_node_base
{
_Tp _M_data;
};
继承下的构造顺序先基类再子类。
析构相反先子类再基类。需要注意的是基类析构函数必须定义为virtual 否则基类无法析构。
在公有继承中,基类对派生类及其对象的操作,只能影响到那些从基类继承下来的成员.如果想要用基类对非继承成员进行操作,则要把基类的这个函数定义为虚函数. 析构函数自然也应该如此:如果它想析构子类中的重新定义或新的成员及对象,当然也应该声明为虚的. 如果不需要基类对派生类及对象进行操作,则不能定义虚函数,因为这样会增加内存开销.当类里面有定义虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间.所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数.
继承下来的纯虚函数基类可以有其定义,但是不能有此基类的实例。
复合
表示 has-a
template <class T, class Sequence = deque<T> >
class queue {
...
protected:
sequence c; //底层容器
public:
bool empty() const { return c.empty; }
size_type size() const { return c.size(); }
refernce back() { return c.back(); }
void push (const T& x) {.push_back(x); }
void pop() { c.pop_front(); }
}
复合关系下的构造与析构
先调用Component 的default构造函数 在执行自己的构造函数。
析构相反先执行自己的析构函数再调用Component的析构函数。
复合的两种模式:
- Adaptor 适配
- Delegation 委托
适配:
Composite 实例:
委托:
Composite 指针:
此处delegation 和 adaptor 与 Design Pattern 有出入。
Inheritance + Composition 的构造与析构:
构造由内而外先调用base 的default 构造函数再调用 component的构造函数,最后自身。
析构相反先调用自身析构函数,再调用component,最后调用调用base。
Inheritance + Delegation 可以实现observer模式,prototype模式。
- Obsever 模式
class Subject
{
int m_value;
vector<Obsever*> m_views;
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_view.size();i++)
m_views[i]->update(this, value);
}
};
Observer
class Observer
{
public:
virtual void update(Subject* sub, int value) = 0;
};
2.prototype 模式:
#include <iostream>
enum imageType
{
LAST,SPOT
};
class Image
{
public:
virtual void draw() = 0;
static Image* findAndClone(ImageType);
protected:
virtual Image* clone() = 0;
//As each subclass of Image is declared, it registers its prototype
static void addPrototype(Image *image)
{
_prototype[_nextSlot] = image;
}
private:
//addPrototype saves each registered prototype here
static Image* _prototype[10];
static int _nextSlot;
};
Image *Image::_prototype[];
int Image::_nextSlot;
//Clint calls this public static member function when it needs an instance of an Image subclass
Image * image:: findAndClone(imageType type)
{
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 cone() is called call the one-argument ctor with a dummy arg
Image *clone() {
retrurn new LandSatTmage(1);
}
protected:
// This is only called from cone()
LandSatImage(int dummy) {
_id = _count++;
}
private:
//mechanism for initializing and Image subclass-this causes the default ctor to be called, which registers the subclass's prototype
static LandSatImage _landSatImage;
//This only called when the private static data men=mber is inited LandSatImage() {
addPrototype(this);
}
//Nominal state per instance mechanism
int _id;
static int count;
};
//Regiser the subclass's prototype
LandSatImage LandSatImage::_landSatImage;
//Initialize the state per instance mechanism
int LandSatImage::_count = 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;