7.1 定义抽象数据类型
7.1.1 设计Sales_data类
7.1.2 定义改进的Sales_data类
struct Sales_data
{
string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price() const;
string bookNo;
unsigned units_sold = 0;
double revenus = 0.0;
};
Sales_data add(const Sales_data&, const Sales_data&);
ostream& print(ostream&, const Sales_data&);
istream& read(istream&, Sales_data&);
- 成员函数的声明必须在类的内部,定义既可以在类的内部也可以在类的外部
- 定义在类内部的函数是隐式的
inline
函数
const成员函数
string isbn() const { return bookNo; }
这里const
是修饰this
指针,说明此处的this
是一个指向常量的指针,所以常量成员函数不能修改调用它的对象的内容
常量对象,以及常量对象的引用或指针都只能调用常量成员函数
类作用域和成员函数
在类外部定义的成员函数需要带上类名和作用域解析运算符
double Sales_data::avg_price() const {
if (units_sold)
return revenus / units_sold;
else
return 0;
}
定义一个返回this对象的函数
Sales_data& Sales_data::combine(const Sales_data& rhs) {
units_sold += rhs.units_sold;
revenus += rhs.revenus;
return *this;
}
7.1.3 定义类相关的非成员函数
一般来说,如果非成员函数是类接口的组成部分,则这些函数的声明应该与类在同一个头文件内
// 输入的交易信息包括ISBN、售出总数和售出价格
istream& read(istream& is, Sales_data& item) {
double price;
is >> item.bookNo >> item.units_sold >> price;
item.revenus = price * item.units_sold;
return is;
}
ostream& print(ostream& os, const Sales_data& item) {
os << item.isbn() << " " << item.units_sold << " "
<< item.revenus << " " << item.avg_price();
return os;
}
IO类属于不能被拷贝的类型,因此只能通过引用来传递
定义add函数
Sales_data add(const Sales_data& rhs, const Sales_data& lhs) {
Sales_data sum = lhs;
sum.combine(lhs);
return sum;
}
7.1.4 构造函数
合成的默认构造函数
类通过一个特殊的构造函数来控制默认初始化过程,这个函数叫做默认构造函数,无须任何实参
- 如果存在类内的初始值,用它来初始化成员,如
units_sold
和revenus
- 否则,默认初始化,将
bookNo
初始化为空字符串
只有当类没有声明任何构造函数时,编译器才会自动地生成默认构造函数
定义Sales_data的构造函数
Sales_data() = default;
该构造函数不接受任何实参,所以它是一个默认构造函数,我们定义这个构造函数的目的仅仅是因为我们既需要其他形式的构造函数,也需要默认的构造函数
构造函数初始值列表
Sales_data(const string& s): bookNo(s) {}
Sales_data(const string& s, unsigned n, double p):
bookNo(s), units_sold(n), revenus(p * n) {}
在类的外部定义构造函数
Sales_data::Sales_data(istream& is) {
read(is, *this);
}
7.1.5 拷贝、赋值和析构
尽管编译器能替我们合成拷贝、赋值和销毁的操作,但是,对于某些类来说合成的版本无法正常工作。特别是,当类需要分配类对象之外的资源时,合成的版本常常会失效,所以只能自己写
不过,如果类包含vector
或string
成员,则其拷贝、赋值和销毁的合成版本能够正常工作