欢迎光临散文网 会员登陆 & 注册

C++ 类

2023-04-11 20:23 作者:S-a-i_  | 我要投稿

类的基本思想是数据抽象封装

数据抽象是一种依赖于接口实现分离的编程技术,类的接口包括用户所能执行的操作;类的实现包括类的数据成员、负责接口实现的函数体以及定义类所需要的各种私有函数。

封装实现了类的接口和实现的分离,封装后的类隐藏了它的实现细节,类的用户只能使用接口而无法访问实现部分。

类要想实现数据抽象和封装,需要首先定义一个抽象数据类型。

一般来说类的设计者考虑类的实现过程,而类的程序员则只需要抽象的思考类做了什么,无需真正了解如何实现。



设计Sales_data类

我们将在后面学习如何自定义运算符,现在我们只定义普通函数形式。

我们假设Sales_data的接口应该包含以下操作

1一个isbn成员函数,用于返回对象的ISBN编号

2一个名为combine成员函数,用于将一个Sales_data对象的加法

3一个名为add的函数,执行将两个Sales_data对象的加法

4一个read函数,将数据从istream读入到Sales_data对象中

5一个print函数,将Sales_data对象的值输出到ostream


使用Sales_data类

对于大部分人来说,我们只需要知道如何使用别人提供的接口。

此函数用来实现上述说明的五条操作的接口。


定义Sales_data类

我们定义bookNo(string)、units_sold(unsigned)、revenue(double),分别表示ISBN编号、书的销量、书的总收入。

如前面所说,我们类包含两个成员函数,combine和isbn,此外我们还赋予Sales_data另一个成员函数用于返回书的平均价格,命名为avg_price,因为avg_price并非通用,所以它属于类的实现的一部分,而不是接口的一部分。

定义和声明成员函数的方式和普通函数一样,成员函数的声明必须在类的内部,定义内外没有要求,作为接口组成部分的非成员函数(add,read,print)他们的定义和声明都在类的外部。

注意:定义在类内部的函数是隐式的内联(inline)函数


定义成员函数

尽管所有成员都必须在类的内部声明,但是成员函数体的定义不限制内外,我们的函数isbn定义在类内,combine和avg_price定义在了类外。

我们先介绍isbn函数,它的参数列表为空返回一个string对象,用于返回bookNo数据成员。


引入this

对于isbn成员函数的调用,我们会使用点运算符,来访问Sales_data类型的对象的isbn成员。后面我们将介绍一种例外的形式,当我们调用成员函数时,实际上是替某个对象调用它,如果isbn指向bookNo,则他隐式的指向调用该函数的对象的成员,所以实际上他隐式的返回Sales_data对象的bookNo(即total.isbn()函数既是total.bookNo。

成员函数通过一个名为this的额外的隐式参数来访为调用它的哪个对象,当我们调用一个成员函数时,用请求该函数的对象地址初始化this。例如如果调用total.isbn(),则编译器负责把total的地址传递给isbn的隐式形参this,可以等价的认为编译器将该调用重写为了

其中调用Sales_data的isbn成员时传入了total的地址。

在成员函数内部,我们可以直接使用调用该函数的对象的成员,而无须通过成员访问运算符来做到这一点,因为this所指的正好是这个对象,任何对类成员的直接访问都被看做this的隐式引用,也就是说当isbn使用bookNo时,他隐式的使用this指向的成员,就像我们书写了this->bookNo。

对我们来说this形参是隐式定义的,实际上任何自定义名为this的参数或变量的行为都是非法的,我们可以在成员函数体内部使用this,因此尽管没有必要,但是我们还是能把isbn定义为下面的形式

因为this的目的总是指向“这个”对象,所以this是一个常量指针,我们不允许修改this中保存的地址。


引入const成员函数

isbn函数的另一个关键之处是紧随参数列表之后的const,这里const的作用是修改隐式this指针的类型。

默认情况下,this的类型是指向类类型非常量版本的常量指针,在上述例子中,this的类型是Sales_data *const,尽管const是隐式的,但他仍然需要遵循初始化规则,意味着我们不能把this绑定到一个常量对象上。这一情况也就使我们不能在一个常量对象上调用普通的成员函数。

如果isbn是一个普通函数而且this是一个普通的指针参数,则我们应该把this声明称const Sales_data *const,毕竟isbn的函数体内不会改变this所指的对象,所以把this设置为指向常量的指针有助于提高函数的灵活性。

然而,this是隐式的并且不会出现在参数列表中,所以在哪儿将this声明成指向常量的指针就成为我们必须面对的问题,C++允许把const放在成员变量的参数列表之后,此时紧跟在参数列表后的const表示this是一个指向常量的指针,像这样使用const的成员函数被称作常量成员函数

因为this是指向常量的指针,所以常量成员函数不能改变调用他的对象的内容,即isbn只能读取调用他的对象的数据成员,不能写。

注意:常量对象、常量对象的引用或指针都只能调用常量成员函数。


类作用域和成员函数

类的成员函数定义嵌套在类的作用域之内,因此isbn中用到的bookNo其实就是定义在Sales_data内的数据成员。

注意:即使bookNo定义在isbn之后isbn还是可以使用bookNo,因为编译器分两步处理类,首先编译成员的声明,然后才轮到成员函数体。


在类的外部定义成员函数

与其他函数一样,我们在类外定义成员函数时必须和声明匹配,即返回列表、参数列表、函数名和声明一致。

如果成员被声明成常量成员函数,那么它的定义也必须在参数列表后明确指定const属性,同时类外部定义的成员的名字必须包含他所属的类名。

units_sold和revenue其实隐式的使用了Sales_data的成员。


定义一个返回this对象的函数

函数combine的设计类似于+=,调用该函数的对象代表的是赋值运算符左侧的对象,右侧对象则通过显式的实参被传入函数。

当我们调用

total的地址被绑定到隐式的this参数上,而rhs绑定到了trans上,因此上述语句等价于把trans.units_sold加到total.units_sold上。

值得注意的是,我们的返回类型和返回语句,如前面所述,我们无须使用隐式的this指针访问函数调用者的某个具体成员,而是需要把调用函数的对象当作一个整体来访问。所以用解引符解引this来返回调用这个函数的对象,即total。



这一章基本是把C++ primer上的原文照搬下来了,确实非常的重要和难以理解(对作者来说

C++ 类的评论 (共 条)

分享到微博请遵守国家法律