7.1定义抽象数据类型抽象数据类型的最大特点是其具有很高的封装性

7.1 定义抽象数据类型

抽象数据类型的最大特点是其具有很高的封装性,我们无法直接访问其内部的数据,甚至我们不清楚其内部都有哪些类型的数据,我们仅使用其提供的各种接口(api)来对其数据进行访问和操作。

C++中的类就是一种抽象的数据类型,类的基本思想就是数据抽象和封装。

仅由一组数据组成的结构体并不是一种抽象的数据类型,因为我们能直接访问其内部数据,而不是通过接口访问。如下的Sales_data

如果想要将书的交易记录Sales_data定义为一个抽象数据类型,我们需要提供一组操作(接口),每次交易只调用这些操作,这样就可以将数据封装起来。

(1)设计Sale_data类

书的交易记录Sale_data包含的数据有:书的标号 bookNo(定义为 string类对象),书的销量 units_sold(定义为 unsigned类型)和交易总价 revenue(定义为 double类型),使用这三个数据类型就可以完整的描述每单的交易了;除了对每单交易的描述外,还应提供哪些操作呢?

我们可以设计了这样一些操作:

a.每单交易的录入read()和打印该单交易print()

b.获取每单交易的参数:获取书编号getBookNo(),获取销量getUnitsSold(),获取销售总价getRevenue()

c.实现同一本书的多单交易的汇总统计(将一单交易加到另一单上)combine()

代码如下:

先编写头文件Sales_data ,将Saes_data类定义在头文件里 //注意,头文件名需要与类名一致,这是规范各文件名中类定义一致,非语法强制要求。

Sales_data类定义

#ifndef SALES_DATA_H
#define SALES_DATA_H  //定义头文件时必须加保护,防止其他.cpp重复引入此头文件。
#include 
#include 
using namespace std;
//统计每单书的交易记录
struct Sales_data {
	//数据成员
	string bookNo;          //书的编号
	unsigned units_sold = 0;     //销量
	double revenue = 0;           //销售总价
	//成员函数   必须在类或结构体内声明,可以在外面定义,但需要在函数名前加 类名::(Sales_data::)
	string getBookNo();
	unsigned getUnitsSold();
	double getRevenue();
	void read();
	void print();
	void combine(Sales_data next);
};
string Sales_data::getBookNo() {
	return bookNo;
}
unsigned Sales_data::getUnitsSold() {
	return units_sold;
}
double Sales_data::getRevenue() {
	return revenue;
}
void Sales_data::read() {
	cout << "请输入一条交易" << endl;
	cout <> bookNo;
	cout <> units_sold;
	cout <> revenue;
}
void Sales_data::print() {
	cout << "编号:" << bookNo << "  卖出" << units_sold << "本" << "  总价:" << revenue <units_sold += next.units_sold;
	this->revenue += next.revenue;
}
#endif // !SALES_DATA_H

主程序(输入一批交易)

 int main() {
	Sales_data toutal, next;
	int k=1;
	toutal.read();
	while (k!=-1)
	{
		next.read();
		if (toutal.getBookNo() == next.getBookNo()) {
			toutal.combine(next);
		}
		else {
			toutal.print();
			toutal = next;
		}
		cout <> k;
	}
	toutal.print();
	return 0;
}

通过以上,定义了描述每单交易的必要参数,以及每单交易和多单交易之前可能会用的的操作,这样,Sale_data类基本就设计好。但还需要打磨一下设计的细节:

需要先介绍两个概念:

引入this指针

通过对象.成员函数调用时,形参表里会隐式的传入一个指向该对象的常量指针this,实际上在成员函数内使用对象的数据成员时,是隐式的使用this.数据成员.

this指针始终都指向调用对象,所以this都是常量指针 (type * const类型)

如toutal.getBookNo();将隐式传入 this常量指针,存放的是toutal对象的地址(Sales_data *const this=&toutal;)。

引入const成员函数

如果调用对象是一个常量对象时,默认的指针类型是不能指向一个常量对象的,所以需要指定this指针为指向常量的指针,只需要在定义和声明成员函数时,在形参列表后添加关键字const,用以修饰this为指向常量的指针常量。

使用const的成员函数称为常量成员函数,无论是常量对象还是非常量对象都可以调用它,但它只能读取调用对象的数据成员,无权修改调用对象。 (常量对象以及其引用或指针只能调用它的常量成员函数)

知道以上两个概念后,我们可以将getBookNo()等成员函数定义为常量成员函数,如 string Sales_data::getBookNo() const{…}

因为getBookNo()只读取对象的数据成员,无修改对象的操作。

© 版权声明
THE END
喜欢就支持一下吧
点赞200 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片