1.组合与继承
Inheritance(继承)
Composition(复合)
Pelegation(委托)
1.Composition复合,表示has-a
例1.
template<class T>,class sequence=deque<T>
class queue{
...
protected:
sequence c;
public:
//以下完全利用C的操作函数完成
bool empty() const {return c.empty();}
size_type size() const {return c.size();}
reference front() {return c.front();}
reference back() {return c.back();}
//deque是两端可进出,queue是末端进前端出(先进先出)
void push (const value_type& x) {c.push_back(x);}
void pop () {c.pop_front();}
};
一般认为类A有成员变量K,K是B类的对象,则A,B是复合关系
即:
其中queue是容器,deque是被容器拥有的内容。
从内存的角度看
template <class T>
struct Itr{
T* cur;
T* first;
T* last;
T** rode;
...
};
其占用的内存空间为:4*4 byte
例2.
template <class T>
class deque {
protected:
Itr<T> start; //包含Itr类
Itr<T> finish;
T** map;
unsigned int map_size;
};
其占用的内存空间为:16*2+4+4 byte
template <class T>
class queue{
protected:
deque<T> c; //包含deque类
...
};
其占用的内存空间为:40 byte
2.复合关系下的构造函数和析构函数
构造由内而外:
container的构造函数首先调用component的default(默认)构造函数,然后再执行自己。(在component中可能存在几个构造函数,避免不确定情况)
container::container(...)::component(){...};
析构由外而内:
container的析构函数先执行自己,然后再调用component的构造函数。
container::container(...){...~component};
3.delegation(委托).composition by reference.
指针传递也被称为composition by reference.
//file String.hpp
class String {
public:
String();
String(const char* s);
String(const String& s);
String& operator=(const String& s);
~String();
...
private:
StringRep* rep; //pimpl
};
//file String.cpp
#include "String.hpp"
namespace
class StringRep {
friend class String;
StirngRep(const char* s);
~StringRep();
int count;
char* rep;
};
}
String::String(){...}
特点:生命周期不同步
4.Inheritance继承,表示is-a
Struct_List_node_base
{_List_node_base* _M_next;
_List_node_base* _M_prer;
};
template<typename_Tp>
struct_List_node
:public_List_node_base
{
_Tp _M_data;
};
在继承中,父类和派生类的数据是可以完全的继承的
在C++中除了public继承外,还有protected继承和private继承。
5.Inheritance继承关系下的构造和析构
其中Base为父类,Derived为派生类。
构造由内而外:
Derived的构造函数首先调用Base的default(默认)构造函数,然后才执行自己
Derived::Derived(...):Base(){...};
析构由外而内:
Derived::~Derived(...){...~Base()};
Base class的dtor必须是virtual(虚函数)否则会出现undefined behavior.
2.Inheritance(继承)with virtual functions(虚函数)
1.继承函数:子类可以调用父类的函数
non-virtual函数:使用者不希望Derived class(派生类)重新定义这个函数(override,覆写)。
virtual函数:使用者希望Derived class(派生类)重新定义这个函数(override,覆写),这个函数已经有默认函数了。
pure virtual函数:使用者希望Derived class(派生类)一定要重新定义这个函数(override,覆写),这个函没有默认函数(其实可以有定义,这里认为没有)。
class Shape {
public:
virtual void draw() const=0; //pure virtual
virtual void error const std::string& msg); //impure virtual
int object() const; //non-virtual
...
};
例.
class CDocument
{
public:
void OnFileOpen()
{
//这是一个算法,每个cout输出代表一个实际的动作
cout<<"dialog..."<<endl;
cout<<"check file status..."<<endl;
cout<<"open file..."<<endl;
Seralize();
cout<<"close file..."<<endl;
cout<<"update all views..."<<endl;
}
virtual void Serialize(){};
};
class CMyDoc:public CDocument
{
public:
virtual void Serialize()
{
//只有应用程序本身才知道如何读取自己的文件
cout<<"CMyDoc::Serialize()"<<endl;
}
};
int main()
{
CMyDoc myDoc;
myDoc.OnFileOpen();//假设对应(file/open)
};
总结:指向基类的指针在操作它的多态类对象时,会根据不同的类对象,调用其相应的函数,这个函数就是虚函数。
2.Inheritance+Composition关系下的构造和析构
若Base(父类)与Derived(子类)为继承关系,Derived与Component为复合关系
构造函数先调用Base或Component的构造函数
若若Base(父类)与Derived(子类)为继承关系,Base与Component为复合关系
先调用Component的构造函数,在调用Base的构造函数,再调用Derived的构造函数
3.委托相关设计
1.两种设计模式的简介
Compositie模式
class Component
{
int value;
public:
Component(int val) {value=val;}
virtual void add(Component*){}
};
class Composite:public Component
{
vector<Component*>c;
public:
Composite(int val):Component(val){
c.push_back(elem);
}
...
};
class Primitive:public Component
{
public:
Primitive(int val):Component(val){}
};
Prototype模式
Prototype原型模式是一种创建型设计模式,它主要面对的问题是:“某些结构复杂的对象”的创建工作;由于需求的变化,这些对象经常面临着剧烈的变化,但是他们却拥有比较稳定一致的接口。