第二章_变量和基本类型_2.6自定义数据结构

数据结构是把一组相关的数据元素组织起来然后使用它们的策略和方法。

2.6.1 定义Sales_data 类型

struct Sales_data{
    
    
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
};

别忘记在类定义的最后加上分号。

类数据成员 (data member)

类的数据成员定义了类的对象的具体内容,每个对象都有自己的一套数据拷贝。

可以为数据成员提供一个类内初始值 (in-class initializer) 。创建对象时,类内初始值用于初始化数据成员,没有类内初始值的成员将被默认初始化。

2.6.2 使用 Sales_data 类

写一段程序实现求两个交易相加结果的功能。程序的输入是两条交易记录

0-201-78345-x 3 20.00
0-201-78345-x 6 25.00

每笔交易记录着图书的 ISBN 编号、售出数量和售出单价

添加两个 Sales_data 对象

Sales_data data1, data2;

Sales_data 对象读入数据

读入一笔交易

double price = 0; // 书的单价,用于计算销售收入
// 读入第 1 笔交易: ISBN、销售数量、单价
std::cin >> data1.bookNo >> data1.units_sold >> price;
// 计算销售收入
data1.revenue = data1.units_sold * price;

读入第 2 笔交易

std::cin >> data2.bookNo >> data2.units_sold >> price;
// 计算销售收入
data1.revenue = data2.units_sold * price;

输出两个 Sales_data 对象的和

检查两笔交易涉及的 ISBN 编号是否相同,若相同输出他们的和,否则输出报错信息。

if(data1.bookNo == data2.bookNo){
    
    
    unsigned totalCnt = data1.units_sold + data2.units_sold;
    double totalRevenue = data1.revenue + data2.revenue;
    std::cout << data1.bookNo << " " << totalCnt << " " << totalRevenue;
    if(totalCnt != 0)
        std::cout << totalRevenue / totalCnt << std::endl;
    else
        std::cout << "(no sales)" << std::endl;
    return 0;
} else {
    
    
    std::err << "Data must refer to the same ISBN " << std::endl;
    return -1;
}

2.6.3 编写自己的头文件

头文件通常包含那些只能被定义一次的实体,如类、const 和 constexpr 变量等。头文件也经常用到其他头文件的功能。

预处理器概述

确保头文件多次包含仍能安全工作的常用技术是预处理器 (preprocessor),更具体的是使用头文件保护符(header guard)。

预处理变量有两种状态:已定义和未定义。

#define指令把一个名字设定为预处理变量,#ifdef当且仅当变量为已定义时为真,#ifndef当且仅当变量未定义时为真。一旦检测结果为真,则执行后续操作直至遇到#endif指令为止。

#ifndef SALES_DATA_H
#define SALES_DATA_H
#include <string>
...
#endif

整个程序中的预处理变量包括头文件保护符必须唯一,通常的做法是基于头文件中类的名字来构建保护符的名字,同时一般预处理变量的名字全部大写。