GeekBandC++开发工程师第三周学习笔记

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

3.1.1 复合(Composition)

template class Sequence = deque >

class queue {

  . . .

protected:

     Sequence c;

public:

      bool empty() const { return c.empty(); }

      size_type size() const  { return s.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(); }

};

3.1.2(Adapter:)改造

//No:1

template 

class queue{

...

protected c;//拥有模块2

...

};

//No:2

template 

class queue{

protected:

Itr strat;//拥有模块3,sizeof:16

Itr finish;

T** map;//指针的指针,4个字节

unsigned int map_size;//4个字节

};

//No:3

template 

struct Itr{

T* cur;//sizeof:4*4

T* first;

T* last;

T** node;

...

};

3.1.3复合关系下的构造函数和析构函数:

构造由内而外:Container::Component(...): Component() {...};

Container的构造函数首先调用Component的default构造然后才执行自己

析构由外而内:Container :: ~Container(...) { ... ~Component() }

Container的析构函数首先执行自己,然后才调用Component的析构函数

3.2 委托:两个类之间相连

class String{

public:

String();

~String();

String(const char*s);

String(const String& a);

String &operator=(const String& s);

private:

StringRep* rep;//等到需要用到StringRep时才去创建StringRep类

};

class StringRep{

friend class String;

StringRep(const char* s);

~StringRep();

int count;

char* rep;

}

3.3.1 继承:

struct _List_node_base

{

_List_node_base* _M_next:

_List_node_base* _M_prev;

};

template

struct _List_node :public _List_node_base

{

_Tp   _M_data;//它除了拥有自己的东西以外,还拥有基类的两个东西

};

3.3.2基类的析构函数必须是virtual,否则会出现undefined behavior

在继承的情况下,构造由内而外:Derived::Derived(...) : Base() {...};

Derived的构造函数首先调用基类的默认构造函数,然后才执行自己

析构由外而内:Derived的析构函数首先执行自己,然后才调用基类的析构函数

Derived::~Derived(...){... ~Base() };

3.3.3

non-virtual函数:你不希望derived class 重新定义它

virtual函数:你希望derived class重新定义它,且它已有默认定义。

pure virtual函数:你希望derived class一定要重新定义它,你对他没有默认定义。

3.4 纯虚函数:virtual 函数类型 函数名(参数表)=0;

声明为纯虚函数后,基类中就不再给出函数的实现部分,且纯虚函数不具备函数的功能,不能被调用。

作用:在基类中为其派生类保留一个函数的名字。以便派生类根据需要对它进行重载

3.5.  inheritance+Composition关系下的构造和析构:

派生类中有基类的part,但派生类中又有Component,这时,调用顺序是基类=Component.>派生类

派生类中有基类的part,而基类part中又有Component时,这时调用顺序为:Component>基类>派生类,析构函数正好相反

委托+继承:

class Subject{

int m_value;

vector m_views;//容器里的类型为Observe*

public:

void attach(Observe* obs)

m_views.push_back(obs);

void set_val(int value)

{

m_value = value;

motify();

}

void notify()

{

for(int i=0;i

m_views[i]->update(this,m_value);

}

};

class Observe{

public:

virtual void update(Subject* sub,int value)const =0;

};

委托+继承:

容器里面的东西一定要放一样的大小,指针是最优选

变量名:partname

#nclude

enum imageType{LAST,SPOT};//枚举

class Image{

public:

virtual void draw()=0;

static Image* findAndClone(imageType);

protected:

virtual imageType return Type()=0;

virtual Image* clone() =0;//要求子类必须对其进行编译

static void assProtype(Image *image)//静态成员函数

{

_prototypes[_nextSlot++]

}

private:

static Image* __prototypes[10];

static int _nextSlot;//class当中的静态date,一定要在这个类外做一次定义,分配内存

};

Image *Image::_prototypes[];

int Image::_nextSlot;

Image *Image::findAndClone(imageType type)

{//当下面所有的子类把自己的一份原型放上去之后填充的数组

for(int i=0;i<_nextSlot;i++)

{

if(_prototypes[i]->() ==type)//找到一个原型之后,调用clone(),就做了一个副本

return _prototypes[i]->clone;

}


public继承和is-a之间的等价关系听起来颇为简单,但有时候会误导人

企鹅是一种鸟,这是对的;鸟会飞,这也对的。但企鹅会飞吗?

class Bird{

public:

virtual void fly();//鸟会飞

...

};

class Penguin:public Bird{//企鹅是一种鸟

...

};

这个代码但是是行得通的,但是那不是真的。

上述例子中,有一个与事实不符的error。如果谨慎一点,应该是:有的鸟会飞,有点鸟不会飞。来塑模出较佳的真实性:

class Bird{

public:

...//没有声明fly()函数

};

class FlyingBird:public Bird{

public:

      virtual void fly();//鸟会飞

       ...

};

class Penguin:public Bird{//企鹅是一种鸟

...

};

这样的继承体系才能比原先的设计更能忠实反映出真正的意思。

现在,如果非得要求企鹅会飞,那编译器会不满:

Penguin p;

p.fly();//错误

一个好的接口可以防止无效的代码通过编译,因此应该采取“在编译期拒绝企鹅飞行”的设计,而不是“只在运行期间才能侦测它们”的设计。

所以,is-a并不是唯一存在于类之间的关系。

你可能感兴趣的:(GeekBandC++开发工程师第三周学习笔记)