第十章 对象和类
通常,C++程序员将接口(类定义)放在头文件中,并将实现(类方法的代码)放在源代码文件中。
在oop中,通常把对象成员函数的调用称作发送消息给对象。
访问控制关键字:private(类默认的访问控制)、public(结构体默认的访问控制)、protected。
将实现细节放在一起,并将它们与抽象分开的思想称为封装。
数据隐藏(将数据放在类的私有部分中)是一种封装;
将实现细节隐藏在私有部分(私有成员函数),也是一种封装;
将类声明和类函数的定义放在不同文件中,亦是一种封装。
类和结构的区别
1. 默认访问类型不同。类是private,结构是public;
2. C++程序员实用类来实现类描述,而把结构限制为只表示纯粹的数据对象。
实现类的成员函数要满足两个特殊特征:
1. 定义成员函数时,使用作用于解析运算符(::)来标识函数所属的类;
2. 类方法可以访问类的private组件。
位于类声明中的私有成员函数将自动成为内联函数,可以在类声明之外定义(内联)成员函数。
类的构造函数和析构函数
构造函数
初始化对象时自动调用构造函数:
//假设有一个Stock类 Stock A = Stock("apple", 250, 1.25);//对象A的初始化1 Stock A("apple", 250, 1.25);//对象A的初始化2
构造函数的函数名与类名相同。
类的构造函数没有返回类型。
定义构造函数的参量名不应与类成员名相同。
默认构造函数
默认构造函数是,未提供显式初始值时,用来创建对象的构造函数。(避免创建未初始化对象)
创建默认构造函数的方法:
1. 给已有构造函数的说有参量提供默认值;
2. 通过函数重载来定义另一个没有参数的构造函数。
调用默认构造函数:
Stock A;//隐式地调用默认构造函数 Stock B();//显式地调用默认构造函数
析构函数
对象过期时(作用域失效)时,将自动调用析构函数(每个类对象都必须有一个析构函数),一般用析构函数完成清理工作。
只需把函数名定义为“类名前加~”即可创建析构函数,而不需要任何参数。
如果程序员没有创建析构函数,则程序将隐式地声明一个默认析构函数。
C++11可将列表初始化应用于类。
Stock hot_hip = {"apple", 100, 45.0}; Stock jock {"SuperMan", 200, 2.3};
在类成员函数声明和定义的开头后置const,可以确保调用对象不被类成员函数修改
//函数声明 void show() const; //函数定义 void show() const { ... }
对象初始化的其它情形
Bozo *pc = new Bozo("popo", "Le Peu");//动态对象 Bozo tubby = 32;//单参数构造函数的情形
this指针指向用来调用成员函数的对象。
类作用域
C++的函数名称的作用域可以是全局的但不能是局部的。C++类引入了一种新的作用域:类作用域(在类中定义的名称的作用域为整个类)。
作用域为类的常量
不允许在类中声明const常量,因为声明只是描述对象的形式,而不能创建对象。
但有两种方法可以声明作用域为类的常量:
1. 在类中声明一个枚举;
2. 在const限定符前使用关键字static(该常量与静态变量存储在一起,而不是存储在对象中)。
在C++98中只能使用这种技术声明值为整数或枚举的静态常量,而不能存储double常量。(但C++11消除了这个限制)
C++11提供了一种新的枚举——作用域内枚举(其枚举的作用域为类):
enum class egg {Small, Medium, Large};// or enum struct egg {Small, Medium, Large};
可以使用作用域解析运算符访问枚举成员。
枚举类成员不能像常规枚举一样,隐式地转换为某种底层整型类型(提高了作用域内枚举的类型安全),但可以进行强制类型转换。
int Frodo = int(egg::Small)
C++11允许选择底层整型类型(默认为int):
enum class : short egg {Small, Medium, Large};//:short将底层整型类型指定为short