Sales_data.h
1 #ifndef SALES_DATA_H 2 #define SALES_DATA_H 3 4 #include "Version_test.h" 5 6 #include <string> 7 #include <iostream> 8 9 class Sales_data { 10 friend Sales_data add(const Sales_data&, const Sales_data&); 11 friend std::ostream &print(std::ostream&, const Sales_data&); 12 friend std::istream &read(std::istream&, Sales_data&); 13 public: 14 // constructors 15 // using the synthesized version is safe only 16 // if we can also use in-class initializers 17 #if defined(IN_CLASS_INITS) && defined(DEFAULT_FCNS) 18 Sales_data() = default; 19 #else 20 Sales_data(): units_sold(0), revenue(0.0) { } 21 #endif 22 #ifdef IN_CLASS_INITS 23 Sales_data(const std::string &s): bookNo(s) { } 24 #else 25 Sales_data(const std::string &s): 26 bookNo(s), units_sold(0), revenue(0.0) { } 27 #endif 28 Sales_data(const std::string &s, unsigned n, double p): 29 bookNo(s), units_sold(n), revenue(p*n) { } 30 Sales_data(std::istream &); 31 32 // operations on Sales_data objects 33 std::string isbn() const { return bookNo; } 34 Sales_data& combine(const Sales_data&); 35 double avg_price() const; 36 private: 37 std::string bookNo; 38 #ifdef IN_CLASS_INITS // using the synthesized version is safe only 39 unsigned units_sold = 0; 40 double revenue = 0.0; 41 #else 42 unsigned units_sold; 43 double revenue; 44 #endif 45 }; 46 47 48 // nonmember Sales_data interface functions 49 Sales_data add(const Sales_data&, const Sales_data&); 50 std::ostream &print(std::ostream&, const Sales_data&); 51 std::istream &read(std::istream&, Sales_data&); 52 53 // used in future chapters 54 inline 55 bool compareIsbn(const Sales_data &lhs, const Sales_data &rhs) 56 { 57 return lhs.isbn() < rhs.isbn(); 58 } 59 #endif
- 成员函数通过隐式this指针访问调用它的对象
- 常量成员函数不可修改调用对象的内容
- 通过非成员函数访问类的私有成员,需在类内将此函数声明为友元(友元声明不是函数声明,函数声明在类外)
- 经常使用的短函数声明为内联函数并在.h文件中定义,类内定义的函数是隐式内联的
- 构造函数没有返回值,不能被声明为const
Sales_data.cpp
1 #include <iostream> 2 using std::istream; using std::ostream; 3 4 #include "Sales_data.h" 5 Sales_data::Sales_data(std::istream &is) 6 { 7 // read will read a transaction from is into this object 8 read(is, *this); 9 } 10 11 double 12 Sales_data::avg_price() const { 13 if (units_sold) 14 return revenue/units_sold; 15 else 16 return 0; 17 } 18 19 // add the value of the given Sales_data into this object 20 Sales_data& 21 Sales_data::combine(const Sales_data &rhs) 22 { 23 units_sold += rhs.units_sold; // add the members of rhs into 24 revenue += rhs.revenue; // the members of ``this'' object 25 return *this; // return the object on which the function was called 26 } 27 28 Sales_data 29 add(const Sales_data &lhs, const Sales_data &rhs) 30 { 31 Sales_data sum = lhs; // copy data members from lhs into sum 32 sum.combine(rhs); // add data members from rhs into sum 33 return sum; 34 } 35 36 // transactions contain ISBN, number of copies sold, and sales price 37 istream& 38 read(istream &is, Sales_data &item) 39 { 40 double price = 0; 41 is >> item.bookNo >> item.units_sold >> price; 42 item.revenue = price * item.units_sold; 43 return is; 44 } 45 46 ostream& 47 print(ostream &os, const Sales_data &item) 48 { 49 os << item.isbn() << " " << item.units_sold << " " 50 << item.revenue << " " << item.avg_price(); 51 return os; 52 }
avg_price.cpp
1 #include <iostream> 2 using std::cerr; using std::cin; using std::cout; using std::endl; 3 4 #include "Sales_data.h" 5 6 int main() 7 { 8 Sales_data total; // variable to hold the running sum 9 if (read(cin, total)) { // read the first transaction 10 Sales_data trans; // variable to hold data for the next transaction 11 while(read(cin, trans)) { // read the remaining transactions 12 if (total.isbn() == trans.isbn()) // check the isbns 13 total.combine(trans); // update the running total 14 else { 15 print(cout, total) << endl; // print the results 16 total = trans; // process the next book 17 } 18 } 19 print(cout, total) << endl; // print the last transaction 20 } else { // there was no input 21 cerr << "No data?!" << endl; // notify the user 22 } 23 24 return 0; 25 }