其他分享
首页 > 其他分享> > 第七章-类基础

第七章-类基础

作者:互联网

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 <iostream>
#include <string>



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 << "书编号:";
	cin >> bookNo;
	cout << "销量:";
	cin >> units_sold;
	cout << "销售总价";
	cin >> revenue;
}
void Sales_data::print() {
	cout << "编号:" << bookNo << "  卖出" << units_sold << "本" << "  总价:" << revenue << endl;
}
void Sales_data::combine(Sales_data next) {
	this->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 << "是否停止录入? ";
		cin >> 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()只读取对象的数据成员,无修改对象的操作。

标签:常量,getBookNo,基础,Sales,next,第七章,toutal,data
来源: https://www.cnblogs.com/newlyx/p/16436953.html