1.5 类简介

1.5 类简介

在解决书店程序之前,我们还需要了解的唯一一个特性,就是如何定义一个数据结构(data structure)来表示销售数据。在C++中,我们通过定义一个(class)来定义自己的数据结构。一个类定义了一个类型,以及与其关联的一组操作。类机制是C++最重要的特性之一。实际上,C++最初的一个设计焦点就是能定义使用上像内置类型一样自然的类类型(class type)。
在本节中,我们将介绍一个在编写书店程序中会用到的简单的类。当我们在后续章节中学习了更多关于类型、表达式、语句和函数的知识后,会真正实现这个类。
为了使用类,我们需要了解3件事情:

  • 类名是什么?
  • 它是在哪里定义的?
  • 它支持什么操作?

对于书店程序来说,我们假定类名为Sales_item,头文件Sales_item.h中已经定义了这个类。
点击转入Sales_item.h的复制网站
如前所见,为了使用标准库设施,我们必须包含相关的头文件。类似的,我们也需要使用头文件来访问为自己的应用程序所定义的类。习惯上,头文件根据其中定义的类的名字来命名。我们通常使用.h作为头文件的后缀,但也有一些程序员习惯.H.hpp.hxx。标准库头文件通常不带后缀。编译器一般不关心头文件名的形式,但有的IDE对此有特定要求。

1.5.1 Sales_item 类

Sales_item类的作用是表示一本书的总销售额、售出册数和平均售价。我们现在不关心这些数组如何存储、如何计算。为了使用一个类,我们不必关心它是如何实现的,只需知道类对象可以执行什么操作。
每个类实际上都定义了一个新的类型,其类型名就是类名。因此,我们的Sales_item类定义了一个名为Sales_item的类型。与内置类型一样,我们可以定义类类型的变量。当我们写下如下语句

	Sales_item item;

是想表达item是一个Sales_item类型的对象。我们通常将“一个Sales_item类型的对象”简单说成“一个Sales_item对象”,或更简单的“一个Sales_item”。
除了可以定义Sales_item类型的变量之外,我们还可以:

  • 调用一个名为isbn的函数从一个Sales_item对象中提取ISBN书号。
  • 用输入运算符(>>)和输出运算符(<<)读、写Sales_item类型的对象。
  • 用赋值运算符(=)将一个Sales_item对象的值赋予另一个Sales_item对象。
  • 用加法运算符(+)将两个Sales_item对象相加。两个对象必须表示同一本书(相同的ISBN)。加法结果是一个新的Sales_item对象,其ISBN与两个运算对象相同,而其总销售额和售出册数则是两个运算对象的对应值之和。
  • 使用复合赋值运算符(+=)将一个Sales_item对象加到另一个对象上。

关键概念:类定义了行为


当你读这些程序时,一件要牢记的重要事情是,类Sales_item的作者定义了类对象可以执行的所有动作。即,Sales_item类定义了创建一个Sales_item对象时会发生什么事情,以及对Sales_item对象进行赋值、加法或输入输出运算时会发生什么事情。

读写Sales_item

既然已经知道可以对Sales_item对象执行哪些操作,我们现在就可以编写使用类的程序了。例如,下面的程序从标准输入读入数据,存入一个Sales_item对象中,然后将Sales_item的内容写回到标准输出:

#include <iostream>
#include "Sales_item.h"
int main()
{
	Sales_item book;
	// 读入ISBN号、售出的册数以及销售价格
	std::cin >> book;
	// 写入ISBN号、售出的册数、总销售额和平均价格
	std::cout << book << std::endl;
	return 0;
}

如果输入:

	0-201-70353-X 4 24.99

则输出为:

	0-201-70353-X 4 99.96 24.99

输入表示我们以每本24.99元的价格售出了4册书,而输出告诉我们总售出册数为4,总销售额为99.96元,而每册书的平均销售价格为24.99元。
此程序以两个#include指令开始,其中一个使用了新的形式。包含来自标准库的头文件时,也应该用尖括号(< >)包围头文件名。对于不属于标准库的头文件,则用双引号(" ")包围。
在main中我们定义了一个名为book的对象,用来保存从标准输入读取出的数据。下一条语句读取数据存入对象中,第三条语句将对象打印到标准输出上并打印一个endl

Sales_item对象的加法

下面是一个更有意思的例子,将2个Sales_item对象相加:

#include<iostream>
#include"Sales_item.h"
int main(){
	Sales_item item1,item2;
	std::cin>>item1>>item2;
	std::cout<<item1+item2<<std::endl;
	return 0;
}

如果输入如下内容:

	0-201-78345-X 3 20.00
	0-201-78345-X 2 25.00

则输出为:

	0-201-78345-X 5 110 22

此程序开始包含了Sales_item和iostream两个头文件。然后定义了两个Sales_item对象来保存销售记录。我们从标准输入读取数据,存入两个对象之中。输出表达式完成加法运算并打印结果。
值得注意的是,此程序看起来与前面的一个程序非常相似:读取两个输入数据并输出它们的和。造成如此相似的原因是,我们只不过将运算对象从两个整数变为两个Sales_item而已,但读取与打印和的运算方式没有发生任何变化。两个程序的另一个不同之处是,“和”的概念是完全不一样的。对于int,我们计算传统意义上的和——两个数值的算数加法结果。对于Sales_item对象,我们用了一个全新的“和”的概念——两个Sales_item对象的成员对应相加的结果。

重要概念:使用文件重定向


当你测试程序时,反复从键盘敲入这些销售记录作为程序的输入,是非常乏味的。大多数操作系统支持文件重定向,这种机制允许我们将标准输入和标准输出与命名文件关联起来:

	$ addItems <infile >outfile

假定$是操作系统提示符,我们的加法程序已经编译为名为addItems.exe的可执行文件(在UNIX中是addItems),则上述指令会从一个名为infile的文件读取销售记录,并将输出结果写入到一个名为outfile的文件中,两个文件都位于当前目录中。

1.5.1节练习


练习1.20:单击下面的链接,将Sales_item.h拷贝到你自己的工作目录中。用它编写一个程序,读取一组书籍销售记录,将每条记录打印看到标准输出上。
点击转入Sales_item.h的复制网站
练习1.21:编写程序,读入两个ISBN相同的Sales_item对象,输出他们的和。
练习1.22:编写程序,读入多个具有相同ISBN的销售记录,输出所有记录的和。

1.5.2 初识成员函数

将两个Sales_item对象相加的程序首先应该检查两个对象是否具有相同的ISBN。

#include<iostream>
#include"Sales_item.h"
int main(){
	Sales_item item1,item2;
	std::cin>>item1>>item2;
	// 首先检查item1和item2是否表示相同的书
	if(item1.isbn() == item2.isbn()){
		std::cout<<item1+item2<<std::endl;
		return 0;	// 表示成功
	} else {
		std::cerr<<"Data must refer to same ISBN"<<std::endl;
		return -1;	// 表示失败
	}
}

此程序与上一版本的差别是if语句及其else分支。即使不了解这个if语句的检测条件,我们也很容易理解这个程序在干什么。如果条件成立,如上一版本一样,程序打印一条计算结果,并返回0,表明成功。如果条件失败,我们执行跟在else之后的语句块,打印一条错误信息,并返回错误标识-1。

什么是成员函数?

这个if语句的检测条件

	item1.isbn() == item2.isbn()

调用名为isbn的成员函数member function)。成员函数是定义为类的一部分的函数,有时也被称为方法method)。
我们通常以一个类对象的名义来调用成员函数。例如,上面相等表达式左侧运算符的第一部分item1.isbn()使用点运算符(.)来表达我们需要“名为item1的对象的isbn成员”。点运算符只能用于类类型的对象,其左侧运算对象必须是一个类类型的对象,右侧运算对象必须是该类型的一个成员名,运算结果为右侧运算对象指定的成员。
当用点运算符访问一个成员函数时,通常我们是想(效果也确实是)调用该函数。我们使用调用运算符( () )来调用一个函数。调用运算符是一对圆括号,里面放置实参(argument)列表(可能为空)。成员函数isbn并不接受参数。因此

	item1.isbn()

调用名为item1的对象的成员函数isbn,此函数返回item1中保存的ISBN书号。
在这个if条件中,相等运算符的右侧运算对象也是这样执行的——它返回item2中的ISBN书号。如果ISBN相同,条件为真,否则为假。

1.5.2节练习


练习1.23:编写程序,读取多条销售记录,并统计每个ISBN(每本书)有几条销售记录。
练习1.24:输入表示多个ISBN的多条销售记录来测试上一个程序,每个ISBN的记录应该聚在一起。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值