《C++Primer Plus 第 10章 对象和类》
知识点梳理:
- OOP特性:
(1) 抽象;
(2) 封装和数据隐藏;
(3) 多态;
(4) 继承;
(5) 代码的重用性。 - 采用OOP方法时,首先从用户的角度考虑对象——描述对象所需的数据以及描述用户与数据交互所需的操作,完成对接口的描述后,需要确定如何实现接口和数据存储。
- 抽象是为了处理事务的复杂性。将问题的本质特征抽象出来,并根据特征来描述解决方案。抽象是通往用户定义类型的捷径,在C++中,用户定义类型指的是实现抽象接口的类设计。
- 类规范有两个部分:
(1) 类声明(private部分);
(2) 类方法定义(public 部分,该方法定义可以只是函数原型,这是抽象思想的体现);
C++将接口(类定义)放在头文件中,并将实现(类的方法的代码)放在源代码中。这样做的好处是,将实现细节从接口设计中分离出来,便于程序的维护(这是封装思想的体现)。 - 接口,是一个共享的框架(注意和Java接口的区别),是程序访问类的成员的桥梁,具体一般通过公有函数来实现。
- 访问控制,C++的OOP中,数据项通常放在private部分,组成类的接口的成员函数大部分放在public部分。不显式声明,默认为private。
- C++中,类是对结构的拓展,他们之间唯一的区别是:结构所有的数据项都是public,而类可以定义为private,访问权限上更强大。C++程序员通常用类类实现类的描述,而把结构限制为纯粹的数据对象(称之为POD,Plain Old Data,普通老式数据)。
- 作用域解析运算符(::)用来标识函数所属的类,类方法可以访问类的private组件。
- 成员函数声明在private组件部分,只能通过public的函数进行访问,而不能直接调用,否则编译器报错。在private组件声明的函数,可以直接定义短小(具体由编译器来决定,一般情况下指不包括循环的顺序简单结构)的函数体,该成员函数将自动成为内联函数;也可以只在类声明中声明原型,在其后的类方法定义中,通过inline限定符来转换成内联函数。
- 内联函数的作用是以空间开销换时间开销,将短小的函数写入类的声明中,那么再编译时,直接在每一个调用出嵌入该函数,功能类似于宏定义,不同的是,宏定义没有类型检查,而内联函数必须有类型。同时还应注意,内联函数的特殊规则,每个使用它们的文件中都必须对其进行定义,因此,内联函数一般在头文件中定义,然后使用时引用。
- 一个类创建所有的对象都有自己独立的存储空间用于存储内部变量和类成员;但是同一个类的所有对象共享类方法。
- 在OOP中,调用成员函数被称之为发送消息,因此将同样的消息发送给两个不同的对象将调用同一个方法,但是该方法被用于不同的对象。
- 客户/服务器模型,客户是实用类程序,而类声明构成了服务器。客户程序员只需了解使用类的借口,服务器程序员则负责实现设计类的细节。
- 构造函数,和类同名,没有类型和返回值,一般用于类成员变量的初始化。
- 默认构造函数,如果没有自定义任何构造函数,C++自动提供默认构造函数。如果定义非默认构造函数而没有提供自定义的默认构造函数,那么编译将会报错。换言之,要么提供自己的构造函数,那么生成对象的时候必须要按照自己写的构造函数输入初始化值,要么自己提供一个默认构造函数。同时还需注意,自动调用构造函数的时候,对象还没有创建完成,此时对象是不存在的。
- 析构函数,负责清理对象的工作,没有类型,与类名相同(前面加~),没有返回值,也没有参数列表。
- 析构函数的调用时刻:
(1) 如果是静态存储类的对象,析构函数在程序结束时自动被调用;
(2) 如果是自动存储类的对象,析构函数子啊程序执行完所在的代码块的时候调用(注意是代码块);
(3) 如果是new运算符创建的对象,在delete之后自动调用; - 构造函数以及析构函数的使用例子:
(1) Class_A a(para);//调用构造函数
(2) Class_A a = Class_A(para);//先创建一个临时对象,然后调用构造函数,然后复制给a,最后再调用析构函数
(3) a=Class_A(para);//此时对象已经存在,调用构造函数可以对其进行赋值,先创建一个临时变量,然后覆盖对象数据,最后调用析构函数清理这个临时变量。 - 构造函数也可以通过C++11新标准,通过大括号进行初始化,如:
(1) Class_A a={para};//para按构造函数的参数顺序进行匹配,可以缺省,缺省变量按变量类型的默认值赋值。
(2) Class_A a={};//调用默认构造函数 - 关键字const保证函数不会修改调用对象,如:
类声明:void show() const;
类定义:void Stock::show() const; - this 指针,每个对象都有一个this指针,指向自己。但是要注意,this是指针,因此要调用其所指向的对象,必须使用解除引用运算符*,即*this。
this指针的一个例子:
Const Stock& Stock::topval(const Stock&s) const
{
If(s.total>total)
return s;
else
return *this;
}
程序说明:第一个const表明该Stock类型的函数返回的对象是const型,第二个表明该函数不会修改调用的参数对象,第三个const表明该函数不会修改函数中访问的对象。对象数组,一个例子:
Stock stocks[10]={Stock(),Stock(para)};
stocks[0]被显示的调用自定义的默认构造函数,stocks[1]显示调用自定义的构造函数,其余元素隐式调用默认构造函数。类的枚举,C++11提供了一种新的枚举,解决了枚举冲突的问题。
enum egg {SMALL,BIG};
enum t_shirt{SMALL,BIG};
// 此时SMALL和BIG冲突,因为egg和t_shirt处于同一作用域中
...
enum class egg{SMALL,BIG};
enum class t_shirt{SMALL,BIG};
//此时SMALL受类的限定,不会与其他的SMALL冲突
此外,在作用域内的枚举,不能隐式的转换为整型。