10.1 过程性编程和面向对象编程
- 最重要的OOP特性:
- 抽象
- 封装和数据隐藏
- 多态
- 继承
- 代码的可重用性
10.2 抽象和类
- 将问题的本质特征抽象出来,并根据特征来描述解决方案
- 指定基本类型完成了三项工作:
- 决定数据对象需要的内存数量
- 决定如何解释内存中的位
- 决定可使用数据对象执行的操作或方法
- 数据隐藏不仅可以防止直接访问数据,还让开发者无需了解数据是如何被表示的
- 不必在类声明中使用关键字private,因为这是类对象的默认访问控制
- 结构的默认访问类型是public
- 类成员函数两个特殊特征:
- 定义成员函数时,使用作用域解析运算符(::)来指出函数所属的类,比如
void stock::update(double price);
- 类方法可以访问类的private组件
- 定义成员函数时,使用作用域解析运算符(::)来指出函数所属的类,比如
- 所创建的每个新对象都有自己的存储空间,用于存储其内部变量和类成员;但同一个类的所有对象共享一组类方法
10.3 类的构造函数和析构函数
为避免成员名和参数名混淆,一种常见的做法是在数据成员名中使用
m_
前缀或者使用后缀_
当且仅当没有定义任何构造函数时,编译器才会提供默认构造函数;为类定义了构造函数后,程序员必须为它提供默认构造函数
定义默认构造函数的方式有两种:
- 给已有构造函数的所有参数提供默认值
- 通过函数重载来定义另一个构造函数—一个没有参数的构造函数
隐式地调用默认构造函数时,不要使用圆括号
与构造函数不同的是,析构函数没有参数,因此Stock析构函数的原型必须是这样的:
~Stock();
在C++11中,可以将列表初始化语法用于类
保证函数不会修改调用对象的语法:将const关键字放在括号后面,比如
void show() const;
和void Stock::show() const
警告:接受一个参数的构造函数允许使用赋值语法将对象初始化为一个值:
Classname object = value;
10.4 this指针
this指针指向用来调用成员函数的对象
每个成员函数都有一个this指针,this指针指向调用对象
10.5 对象数组
- 可以用构造函数来初始化数组元素,在这种情况下,必须为每个元素调用构造函数,可以对不同的元素使用不同的构造函数,如果只初始化了部分元素,那么剩下的就使用默认构造函数
10.6 类作用域
在类中定义的名称(如类数据成员和类成员函数名)的作用域都为整个类,要调用公有成员函数,必须通过对象
声明类只是描述了对象的形式,并没有创建对象,因此,在创建对象前,将没有用于存储值的空间,即不能声明一个常量,但有两种解决方案:
在类中声明一个枚举:
1 2 3 4 5 6
class Bakery { private: enum {Months = 12}; double consts[Months]; }
- 这里使用枚举只是为了创建符号常量,并不打算创建枚举类型的变量,因此不需要提供枚举名,比如
ios_base
类在其公有部分完成了类似的工作,比如ios_base::fixed
等标识符,fixed
就是类的枚举量
- 这里使用枚举只是为了创建符号常量,并不打算创建枚举类型的变量,因此不需要提供枚举名,比如
使用关键字
static
1 2 3 4 5 6
class Bakery { private: static const int Months = 12; double consts[Months]; }
- 在这里,该常量与其他静态变量存储在一起,而不是存储在对象中,被所有的Bakery对象共享
C++11作用域内枚举,为避免两个枚举的枚举量发生冲突,所以C++11提供了一种新枚举,作用域为类:
enum class egg{small medium};
10.7 抽象数据类型
- abstract data type, ADT
- 比如栈就是一种抽象数据类型