2020-02-01

# 第十五章 面向对象程序设计

**三个基本概念:数据抽象、继承和动态绑定**

##15.1 OOP概述

使用继承,可以定义相似的类型并对其相似关系建模

使用动态绑定,可以在一定程度上忽略相似类型的却别,而以统一的方式使用他们的对象

####继承

通过继承联系在一起的类构成一种层次关系。通常在层次关系的根部有一个**基类**,其他类则直接或间接地从基类继承而来,这些继承得到的类成为**派生类**

* 基类将 类型相关的函数 与 派生类不做改变直接继承的函数 区分对待

* 某些函数,基类希望派生类各自定义自己的版本,就将函数声明成**虚函数**virtual

* 派生类必须使用类派生列表明确指出基类。派生列表中基类的前面可以有访问说明符:public/protected/private

```

class Quote{

public:

string isbn() const;

virtual double net_price(size_t n) const;

};

class bilk_quote : public Quote{

public:

double net_price(size_t) const override;

};

```

**用逗号来分隔基类列表**

* 派生类必须对所有重新定义的虚函数进行声明,可以显式注明出来改写的是哪个虚函数:加override

####动态绑定

用同一段代码分别处理Quote和bulk_quote

```

double print(ostream& os,const Quote &item,size_t n){

.......

}

```

因为第二个形参是**_Quote的引用_**,所以也可以用bulk_quote调用这个函数,里面的成员函数就是用bulk_quote的版本了。

**在运行时选择函数的版本**

##15.2 定义基类和派生类

###15.2.1 定义基类

1. 作为继承关系中根节点的类通常都会定义一个虚析构函数,所以基类也要定义

2. 当我们使用**指针或引用**调用虚函数时,该调用将被动态绑定。根据引用或指针所绑定的对象的不同,执行不同类的版本

3. 任何构造函数之外的非静态函数都可以是虚的。

4. virtual只能出现在类内部的声明之前,不能出现在外部。基类一个函数是virtual的,则该函数在派生类中也是virtual的

5. 派生类的成员函数不一定有权访问从基类继承而来的成员。派生类能访问公有成员,不能访问私有成员。同时,基类希望派生类(内部)有权访问该成员,同时禁止其他用户访问,就弄protected:

###15.2.2 定义派生类

我们能将派生类型的对象绑定到其基类的**引用或指针**上,

只继承自一个类的形式的继承被称作“单继承”

####虚函数

如果派生类没有覆盖基类的虚函数,那么就直接继承其在基类中的版本

覆盖的话,在const后面/引用限定符后面添加关键字override

####派生类向基类的类型转换

* 派生类自己的部分和继承的部分不一定是连续储存的

* 我们能将指针和对象绑定到派生类对象中的**基类部分**上

* 这种转换叫**派生类到基类的类型转换**,会隐式转换

####派生类构造函数

* 不能直接初始化继承来的成员,需要使用基类的构造函数

```

bulk_quote(const string& book, double p, size_t qty, double disc)

: Quote(book, p), min_qty(qty), discount(disc) {}

```

将前两个参数传递给quote的构造函数。

首先初始化基类部分,然后按照声明顺序依次初始化派生类的成员

####派生类使用基类成员

可以访问public和protected成员

**派生类的作用域嵌套在基类作用域之内**

####静态成员

如果基类定义了一个静态成员,那么在整个继承体系中只有一个该成员

如果是可访问的,我们可以使用基类或者是派生类使用它

####声明

派生类的声明不需要派生列表

####被用作基类的类

如果想将某类用作基类,那么必须已经定义而不是声明

一个派生类拥有**直接基类**和**间接基类**的子对象

####如果想防止继承,在类名后加一个final

`class NoDerived final {};`

###15.2.3 类型转换和继承

静态类型:总是已知的,它是变量声明时的类型或表达式生成的类型

动态类型:变量或表达式表示的内存中对象的类型,直到程序运行时才可知

如果表达式不是引用和指针,那么动态类型就永远和静态类型一致

####不存在从基类向派生类的隐式类型转换,因为基类没有派生类的成员

##15.3 虚函数

所有的虚函数都必须有定义

你可能感兴趣的:(2020-02-01)