C++:继承、复合和委托

面向对象编程

类与类之间的关系:继承(Inheritance)、复合(Composition)和委托(Delegation)

复合

表示has a:我里面有一个**东西;

template <class T>
class queue{
protected:
	deque<T> c;//底层容器
public:
	//以下完全利用变量c的操作函数完成
	bool empty()const{return c.empty();}
	void pop(){c.pop_front();}
	void push(const value_type& x){c.push_back(x);}
};

在这里插入图片描述

  • queue拥有了dequedeque已经很完美了,由于某些需求,使用queuedeque进行改装
  • 表现出一种设计模式:Adapter
  • 构造和析构(此处queueContainerdequeComponent
    • 构造由内而外Container的构造函数首先调用Componentdefault构造函数,然后才执行自己;
    • 析构由外而内Container的析构函数首先执行自己,然后才调用Component的析构函数;

委托

拥有指向某个类的指针,在想要调用时再调用(委托),也可称为Composition by reference

//file String.hpp
class StringRep;
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;
	StringRep(const char*s );
	~StringRep();
	int count;
	char* rep;
};
}

String::String(){}

在这里插入图片描述

  • String作为接口,而具体的实现在StringRep中进行,即String中有一个指针指向实现Stirng中方法的类
  • Handle/Body(pImpl)
  • 指针可以指向不同的实现类,称为编译防火墙,String可以一直不变,而采取不同的实现,即不同的StringRep
  • 由于是指针连接,则双方生命周期不同。

在这里插入图片描述

  • 共享相同的内容
  • a 修改 Hello,则 copy 一份 Hello 专门给 a 进行修改,bc不变

继承

表示 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,否则会出现 undefined behavior

继承下的虚函数(virtual functions)

在成员函数前加入 virtual 关键字

class Shape{
public:
	virtual void draw()const = 0;   //pure virtual
	virtual void error(const std::string& msg); //impure virtual
	int objectID() const;  //non-virtual,不需要下面的子类覆写

};
class Rectangle:public Shape{...};
class Ellipse:public Shape{...};
  • non-virtual函数:你不希望子类重新定义(override,覆写)它;

  • virtual函数:你希望子类重新定义(override,覆写),你对它已有默认定义;

  • pure virtual函数:你希望子类一定要重新定义(override,覆写)它,你对它没有默认定义;

  • 存在以下应用场景:

    • 通过子类对象调用父类的函数,在父类函数中存在虚函数是在子类中给出的完整实现——Template Method
    • 应用:在不同操作系统中的打开文件的方式,父类给出基本的通用的方法,留下无法决定的使之成为虚函数,在子类中给出不同的实现。

三种关系的复合

继承和复合

  • 重点在于构造函数和析构函数的执行次序

委托和继承

  • 应用场景:PowerPoint开多个窗口
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(Subject* sub,int value)=0;
};

在这里插入图片描述

  • 应用场景:文件系统;对应于设计模式中的Composite
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值