c++ primer 笔记第七章(一)

第七章 类

梗概:这一章介绍了类的定义与概念,以及类的封装类的作用域以及重点讲解了构造函数。最后介绍了类的静态成员。

类的基本思想时数据抽象和封装。数据抽象是指接口的设计与实现。封装是对类设计细节的隐藏,分离了接口的定义与使用。

7.1 定义抽象数据类型

将一些数据进行抽象得到一种抽象的数据类型,有一些特定的组成和操作接口。

7.1.1 设计Sales_data类

对于类来说有两种角色:类的设计者与使用者。使用者不需要知道类的实现细节。

7.1.2 定义改进的Sales_data类

非通用的函数设计为类实现的一部分而非接口的一部分。

定义在类内部的函数是隐式的inline函数。

成员函数都声明在类内,但定义可以是类内或类外。

成员函数通过this指针隐式访问调用它的那个对象。相当于将对象的地址作为实参传递给隐式形参指针this。

this是一个常量指针,指向当前对象的地址不能改变。

紧跟在函数参数列表后面的const表示this是指向常量的指针,这种函数成为常量成员函数。

常量对象,常量对象的引用或指针都只能调用常量成员函数。

编译类的时候首先编译所有成员的声明,之后才轮到成员函数体。

成员函数被声明为const那么定义时也需要声明。

在需要连续调用原对象成员函数时返回引用类型,否则只能得到一个临时量。

7.1.3 定义类相关的非成员函数

如果函数在概念上属于类但不定义在类中,则它一般应与类声明(而非定义)在同一个头文件内。

比如Sales_data类中的read和print函数就是这样,且接收普通的输入输出流引用。

7.1.4 构造函数

类通过一个或几个特殊的成员函数来控制其对象的初始化过程,这些函数叫构造函数。

构造函数没有返回值类型,不能被声明为const类型。即使是const对象的初始化也是。

类通过一个特殊的构造函数控制默认初始化过程,即默认构造函数,没有实参。

如果类没有显示定义任何构造函数,编译器隐式定义合成的默认构造函数。

默认构造函数对对象使用类内初始值初始化,如果没有则对其默认初始化。

一般都要用户定义默认构造函数:一、定义其它构造函数则编译器不合成默认构造函数。

二、对某些类合成构造函数操作错误如含有复合类型的成员的类。

三、有时候编译器无法为某些类合成默认构造函数,如含有没有默认构造函数的其它类成员的类。

Sales_data() = default; 表示要求编译器合成默认构造函数。在类内则内联,类外不内联。

构造函数初始值列表,每个名字后面紧跟括号括起来的成员初始值,如 Sales(string s, int a, int b): bookNo(s),sold(a),re(b){};。

如果某个成员被构造函数初始值列表忽略,那么它的初始化方式和合成默认构造函数一样。

执行一些实际操作的构造函数可以定义在类外部。

7.1.5 拷贝、赋值和析构

初始化变量以及用值的方式传递或者返回一个变量时使用拷贝。

使用赋值运算符时发生对象的赋值操作。

当对象不再存在时执行析构操作,包括vector被销毁时内部存储的变量。

若不主动定义,则编译器合成这些操作。如赋值操作默认每个成员赋值。

对某些类来说合成版本的操作无法进行,特别是需要内存分配的类。不过可以尽量使用vector和string避免。

7.2 访问控制和封装

c++ 访问说明符 public 与 private 。 public成员程序内可见,用来定义接口。private成员可以类内可见,隐藏细节。

类内可以出现0个或多个访问说明符,次数没有限制。

class与struct的区别在于默认访问权限。一般全public用struct。

7.2.1 友元

允许其他类或函数访问类的非public成员,可以声明其为友元。在类内使用friend关键字声明即可。

友元出现在类内位置不限,不过一般集种开始或者结束前。

友元仅仅指定了访问权限,不能代替通常意义的函数声明。因此在外部依然需要声明。

封装的益处:一、用户代码不会破坏封装对象的状态。 二、调整类的实现时无需更改用户代码。

7.3 类的其它特性

7.3.1 类成员再探

定义类型的成员必须先声明后使用,与普通成员有所区别,一般出现在类开始处。using pos = std::string::size_type;

类内定义的成员函数自动inline,外部定义的可以使用关键字inline说明。一般和类定义在同一头文件。

可变数据成员永远不会是const。

类内初始值必须用=或者花括号表示。

7.3.2 返回*this指针的成员函数

返回*this可以是引用或者副本值。

从const成员函数中返回的*this指针是常量引用或者常量对象。

基于const对成员函数进行重载。非常量版本函数对常量对象不可用,非常量对象匹配非常量版本更好。

建议:对于公共代码使用私有功能函数。

7.3.3 类类型

每个类的类型唯一,即使成员列表都一样。

在定义类之前可以先进行声明,如class Screen; 声明后是一个不完全类型,可以定义引用或指针或作为参数和返回值类型。

但是进行创建类时类必须被定义而不是仅仅声明。

7.3.4 友元再探

类可以把非成员函数、其他类和其他类的成员函数定义为友元。友元函数可以定义在类内部,此时内联。

友元类的成员函数可以访问当前类的所有成员。

友元关系不存在传递性。

声明成员函数为友元顺序:一、定义A类,声明A类成员函数b但不定义。

二、定义B类,把A类的b函数声明为B类的友元函数。

三、定义A类的b函数。

声明重载函数的友元需要一一指定。

类和非成员函数的声明不是必须在它们的友元声明之前。

友元函数必须在外部声明之后,类的成员函数或者其它函数才可以进行调用。

猜你喜欢

转载自blog.csdn.net/qq_25037903/article/details/81544627