第七章-类基础
作者:互联网
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