类简介
一个类定义了一个类型,以及与其关联的一组操作。就像内置类型告诉我们数据的类型和能在数据上执行的操作一样,类设计的焦点就是能够定义像内置类型一样的自定义类型,具有我们想赋予它的意义和想在它身上执行的操作。
类的基本思想是数据抽象和封装。数据抽象依赖于接口和实现分离的编程技术。
通过类的封装,把类的成员数据和成员函数封装到类中,一般成员数据属于private,成员函数在public中作为接口对数据成员进行操作。类的用户只能通过接口而无法访问实现的部分。
第七章学习的线索就是通过学习将Sales_data类逐渐完善成Sales_item类。
1.Sales_item类
Sales_item类的作用是表示一本书的总销售额、售出册数和平均售价,能在其身上执行提取Sales_item对象中的书号、<<,>>读写Sales_item对象、=为Sales_item对象赋值、+将两个Sales_item对象相加、+=将一个Sales_item对象加到另一个对象上。
Sales_item对象的C++代码一代版本如下:
//Sales_item.h
#pragma once
#include<iostream>
#include<string>
using namespace std;
class Sales_item {
friend istream& operator>>(istream& is, Sales_item&);
friend ostream& operator<<(ostream& os, Sales_item&);
friend bool operator==(const Sales_item&, const Sales_item&);
friend Sales_item operator+(Sales_item&, const Sales_item&);
public:
Sales_item(const string& s) :_bookNo(s), _sold(0), _revenue(0) {}
Sales_item() : Sales_item(" ") {} //采用委托构造的默认构造函数
Sales_item& operator+=(const Sales_item&);
string isbn()const; //返回书号
double averPrice()const; //返回平均售价
private:
string _bookNo; //书号
unsigned _sold; //销售数量
double _revenue; //收入
};
//Sales_item.cpp
#include"Sales_item.h"
//后面加const表示在isbn成员函数内任意改变成员函数的操作都是不允许的
string Sales_item::isbn()const {
return _bookNo;
}
double Sales_item::averPrice()const {
return _revenue / _sold;
}
Sales_item& Sales_item::operator+=(const Sales_item& rhs) {
if (isbn() == rhs.isbn()) {
_sold += rhs._sold;
_revenue += rhs._revenue;
}
return *this;
}
istream& operator>>(istream& is, Sales_item& rhs) {
double price;
is >> rhs._bookNo >> rhs._sold >> price;
if (is) {//输出成功
rhs._revenue = rhs._sold * price;
}
else { //输出失败则用一个默认构造的Sales_item对象初始化rhs
rhs = Sales_item();
}
return is;
}
ostream& operator<<(ostream& os, Sales_item& rhs) {
os << "书号:" << rhs.isbn() << " 售出量:" << rhs._sold
<< " 平均价格:" << rhs.averPrice()
<< "销售额:" << rhs._revenue << endl;
return os;
}
bool operator==(const Sales_item& lhs, const Sales_item& rhs) {
return lhs.isbn() == rhs.isbn()
&& lhs._sold == rhs._sold
&& lhs._revenue == rhs._revenue;
}
Sales_item operator+(Sales_item& lhs, const Sales_item& rhs) {
Sales_item ret(lhs);
ret += rhs;
return ret;
}
#include<iostream>
#include"Sales_item.h"
int main() {
Sales_item total; //保存和的变量
if (cin >> total) {
Sales_item trans; //存放下一条交易记录
while (cin >> trans) {
//如果下一条交易记录和之前书号相同,则相加
if (total.isbn() == trans.isbn()) {
total += trans;
}
//打印前一本书的销售结果,并开始记录下一本书的销售额
else {
cout << total << endl;
total = trans;
}
}
cout << total << endl;
}
else {
return -1;
}
system("pause");
return 0;
}
输出结果为
2.Sales_data类
Sales_data类只有Sales_item的成员变量。
struct Sales_data{
string _bookNo; //没有类内初始值将默认初始化
unsigned _units_sold=0; //类内初始值
double _revenue=0.0; //类内初始值
};
可以为数据成员提供一个类内初始值。创建对象时,类内初始值将初始化数据成员,没有初始值的成员将被默认初始化。