【GeekBand】 面向对象的编程,类跟类的关系

本周主要讲了三种类跟类的关系,包括复合,委托,以及继承

1.复合

1.1定义

在一个类中以另一个类的对象作为数据成员的,称为类的复合(composition)。

例如以下代码

template
class queue{
...
protected:
  deque c;
public:
   some code
}

上述代码表示,类queue中有个成员是类duque对象,这种情况即为复合,同时deque的功能要比queue要来的多,在some code中,queue的实现则可以直接调用deque的实现,这种情况称之为adapter。

1.2内存布局

#include
using namespace std;
class A
{
    int i;
    int j;
};
class B
{
    A a;
    int k;
};

int main()
{
    cout<<"A size is "<

运行结果如下:

运行结果.png

从结果可以很明显看出,B的大小包括对象a的大小加上自身的一个int

1.3构造与析构

#include
using namespace std;
class A
{
    int i;
    int j;
public:
    A(){cout<<"A ctor"<

运行结果如下:

运行结果.png

首先调用了类A的构造函数,然后调用B自身的构造函数,析构函数过程则相反,即 构造由内而外,析构由外而内

2.委托

2.1 定义

拥有其他类的指针,用指针相连,与复合不同的是,生存期不同步,复合同时构造同时消亡,委托则是在有需要时在创建。如下所示

classStringRep;

classString{

public:

...

private:

StringRep* rep; //里面包含了指向StringRep类的指针;

}

classStringRep{

...

}

2.2 pimpl(pointer to implication)

pimpl的作用是将实现与对外接口分开,分为如下两个部分
Handle:表示对外的接口,即上述String类中的内容;
Body:表示具体的实现,实现则在StringRep类中实现;
Body的怎么变化不影响Handle;Handle怎么修改,Body无需重新编译,也叫编译防火墙;
上述例子通过引用计数来共享内存,当所指字符串内容一致时,指针指向同一块内存,同时记录下指向这片内存的指针数量,如果有指针需要修改内容,则创建一个副本进行修改,同时指向该内存的指针数量减一。

3.继承,表示is-a

3.1声明格式

class 派生类名:继承方式(若不具体指出默认为private) 基类名{    …};

内存分布

#include
using namespace std;
class A
{
    int i;
    int j;
    
};
class B:public A
{
    int k;
};

int main()
{
    cout<<"A size is "<

运行结果如下:


运行结果.png

这种单继承以及没有虚函数的情况下,内存分布和构造析构顺序都与复合类似,都是构造由内而外,析构由外而内,派生类的大小则是基类大小加上private成员中的non static data。

4.虚函数与多态

非虚函数:不希望派生类重新定义它
虚函数:希望派生类重新定义它,且对它已有默认定义
纯虚函数:你希望派生类一定要重新定义它,你对他没有默认定义

classShape{

public:

virtual void draw()const=0; //purevirtual必须被所有子类重新定义;

virtual void error(const std::string& msg); //impurevirtual此处为默认定义,允许子类去重新定义;

int objectID() const; //non-virtual不可被子类重新定义

}

class Rectangle:public Shape{...};

class Ellipse:public Shape{...};

你可能感兴趣的:(【GeekBand】 面向对象的编程,类跟类的关系)