C++面向对象基础(5)-组合和继承
composition 复合
has的关系,在一个类里有另一个类,如下:
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(); }
void push(const value_type& x) { c.push_back(x); }
void pop() { c.pop_front(); }
};
复合是queue里有deque,但是以上例子比较特殊,不仅有复合关系,而且queue的所有函数都是借助deque的函数来实现的——这种关系就是设计模式中的适配器模式。适配器模式就是已经有一个很强大的P1,但是客户想要另一个P2,P1完全满足客户需求,只是名称和接口不一样,于是可以借用P1来完成P2,此时P2就是Adapter。
复合关系框图:

复合关系的构造函数和析构函数:
Container的构造需要先调用Component的default构造函数,然后才执行自己的构造函数:Container::Container(...):[Component()] {...},[]里的是编译器会加上默认的那个构造函数,如果默认的不符合,就需要自己写,先有Component的构造再去执行Container的操作;
Container的析构函数会首先执行自己,然后再调用Component的析构函数:Container::Container(...){ ... [~Component()] },先析构Container再析构Component。
Delegation 委托
也是has的关系,但是用指针相连,Composition by reference。
用String举例如下:
class StringRep;
class String {
public:
String ();
String (const char* s);
String (const String& s); // 拷贝构造
String &operator=(const String& s); // 拷贝赋值
~String (); // 析构函数
...
private:
StringRep* rep; // 委托
};
委托关系框图如下:

StringRep* rep;用的是pimpl的方式,也叫作Handle/Body,将接口和实现分开,上面一段是Handle,下面是实现的Body:
#include "String.cpp"
namespace {
class StringRep {
friend class String;
StringRep(const char* s);
~StringRep();
int count; //引用计数
char* rep;
}
}
String::String() {...}
...
pimpl的好处是 StringRep的指针可以指向不同的实现类,也就是实现方式不会影响客户端,因此也叫作编译防火墙,只需要改动Body即可。
Inheritance 继承
是is的关系
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;
};
继承关系框图:

Base是父类,Derived是子类
同Composition,继承的构造也要由内而外Derived::Derived(...): Base() {...};,析构由外而内Derived::~Derived(...) {... ~Base() };
注意:父类的析构函数必须是虚函数,否则会出现undefined behavior
浙公网安备 33010602011771号