一、继承,复合,委托(类与类之间的关系)
1. Composition(复合): A拥有B即为复合
template <class T>
class queue{
. . .
protected:
deque<T> 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(); }
};
// 类queue中的的成员c是模板deque类型的,这种情况是复合
%%自己已有deque,客户要求与已有类似,就可以创建queue来使用deque的内容
复合关系下的构造和析构
1)构造由内而外(比较稳定)
Container的构造函数先调用Component的default构造函数,然后才执行自己。
Container::Container(...): Component () { ... 外部自己的初始化 };
// 粗体Component部分可以自己写,让编译器调用哪一个,不写的话直接调用默认
2)析构由外而内(要删除,先剖掉外面一层,再一层层向内部)
Container的析构函数首先执行自己,然后才调用Compent的析构函数。
Container::~Container(...) {... ~Component() };
//先把自己的事情做完,再调用内部!
1)2)中次序编译器可以自动完成。
2. Delegation(委托). Composition by reference(虽然用指针,但是学术界只说by reference)
class StringRep;
class String {
public:
String();
String(const char* s);
String(const String& s);
String &operator=(const String& s);
~String();
. . . .
private:
StringRep* rep; //用指针指向为我实现功能的类,rep为一个指向StringRep类的指针
};
class StringRep()
两个类之间委托,就是用指针相连。
3. Inheritance(继承)
1)三种继承方式:
public(比较常用,is a的意思),父类的public和private成员作为派生类的成员时,他们都保持原有的状态,而父类的私有成员仍然是私有的,不能被这个派生的子类访问。
private,父类的public和protected作为私有的,不能被派生的子类访问
protected,父类的所有public和protected都为派生类的protected成员,只能被派生类的成员函数/友元访问,父类的私有成员仍然是私有的。
2)struct和class最本质的一个区别是默认的访问控制:默认的继承访问权限
struct是public,class是private的。
struct A
{char a;};
struct B : A
{char b;}; //此时B是public继承A;如果将struct改成class,B是private继承A的
3)
struct _List_node_base
{
_List_node_base* _M_next;
_List_node_base* _M_prev;
};
templete<typename _Tp>
struct _List_node : public _List_node_base //继承关系
{ _Tp _M_data; };
4)继承关系下的构造和析构
base class的析构函数必须是虚函数
构造要由内而外,子类的构造函数首先要调用父类的默认构造函数,然后才执行自己
Derived::Derived(...): Base() { ... };
析构要由外而内,Derived的析构函数首先执行自己,然后才调用Base的析构函数
Derived::~Derived(...) {... ~Base() };
二、虚函数与多态
继承最重要的是和虚函数搭配~~
函数继承的是对函数的调用权
virtual 成员函数; //虚函数
1.成员函数种类
1)非虚函数(普通函数):不希望子类重新定义(override)它
2)虚函数:希望子类重新定义它,且你对它已有默认定义
3)纯虚函数:希望子类一定要重新定义它,你对它没有默认定义
virtual { } = 0; // 有virtual和=0 eg,virtual void draw( ) const = 0;
2.虚函数应用(继承搭配虚函数)
上图中Application framework,把确定的部分写好,不确定的地方写成虚函数,让子类来定义。
3. 继承+复合关系下的构造和析构
三、委托相关设计
1. 委托+继承
eg,可实现同时打开多个窗口,一个窗口内容变化会影响到另外的窗口
file system文件系统,文件中有目录。。。
如何将他们关联
上述问题解析:容器和类一起用的时候,要在容器中放指针
class Component
{
int value;
public:
Component(int val) { value = val; }
virtual add(Component*) { }
};
class Composite : public Component
{
vector<Component*> c;
public:
Composite(int val): Component(value) { }
void add(Component* elem)
{
c.push_back(elem);
}
...
};
class Primitive: public Component
{
public:
Primitive(int val): Component(val) { }
};
Prototype
类中声明的静态变量,一定要在类外对其进行定义(分配内存)