【共读Primer】5. 篇外篇----关于Sales_item
---恢复内容开始---
先将一段代码贴出,这段代码是结合描述和一些经验写出来的
但是代码并没有仔细的斟酌过,我们共同来分析一下
1 #ifndef SALESITEM_H 2 #define SALESITEM_H 3 #include <iostream> 4 #include <string> 5 6 class Sales_item{ 7 public: 8 Sales_item(const std::string &book):isbn(book),units_sold(0),revenue(0.0){} 9 Sales_item(std::istream &is){ is >> *this;} 10 friend std::istream& operator>>(std::istream &,Sales_item &); 11 friend std::ostream& operator<<(std::ostream &,const Sales_item &); 12 public: 13 Sales_item & operator+=(const Sales_item&); 14 public: 15 double avg_price() const; 16 bool same_isbn(const Sales_item &rhs)const{ 17 return isbn == rhs.isbn; 18 } 19 std::string ISBN(){return isbn;} 20 Sales_item():units_sold(0),revenue(0.0){} 21 public: 22 std::string isbn; 23 unsigned units_sold; 24 double revenue; 25 }; 26 27 using std::istream; 28 using std::ostream; 29 Sales_item operator+(const Sales_item &,const Sales_item &); 30 31 inline bool operator==(const Sales_item &lhs,const Sales_item &rhs){ 32 return lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue && lhs.same_isbn(rhs); 33 } 34 35 inline bool operator!=(const Sales_item &lhs,const Sales_item &rhs){ 36 return !(lhs == rhs); 37 } 38 39 inline Sales_item & Sales_item::operator +=(const Sales_item &rhs){ 40 units_sold += rhs.units_sold; 41 revenue += rhs.revenue; 42 return *this; 43 } 44 45 inline Sales_item operator+(const Sales_item &lhs,const Sales_item &rhs){ 46 Sales_item ret(lhs); 47 ret += rhs; 48 return ret; 49 } 50 51 inline istream& operator>>(istream &in,Sales_item &s){ 52 double price; 53 in >> s.isbn >> s.units_sold >> price; 54 if(in) 55 s.revenue = s.units_sold * price; 56 else 57 s = Sales_item(); 58 return in; 59 } 60 61 inline ostream& operator<<(ostream &out,const Sales_item &s){ 62 out << s.isbn << "\t" <<s.units_sold << "\t" << s.revenue << "\t" << s.avg_price(); 63 return out; 64 } 65 66 inline double Sales_item::avg_price() const{ 67 if(units_sold) 68 return revenue/units_sold; 69 else 70 return 0; 71 } 72 #endif // SALESITEM_H
本次分析完全建立在我的个人经验之上,知识有可能超过关于本书中已经了解过的内容。
我将尽量使用地址是门槛的角度进行逐行的进行代码解析,以求尽量让更多的人能够看懂
#ifndef SALESITEM_H #define SALESITEM_H // ...中间是代码部分... // 在文件的末尾部分 #endif // SALESITEM_H
这部分是一个防止头文件重复包含的宏定义。
运行原理:
编译器会有一些预定义宏,第一行的#ifndef则是去检查预定义宏中是否存在SALESITEM_H这个名称,如果没有找到的话顺序运行。
如果找到的话跳过直到 #endif 的部分。
#include <iostream> #include <string>
包含两个需要的库文件,输入输出和字符串
class Sales_item{
// ...代码定义...
};
定义一个类,名称是Sales_item 定义部分,直到匹配的大括号分号结束
public:
Sales_item():units_sold(0),revenue(0.0){}
Sales_item(const std::string &book):isbn(book),units_sold(0),revenue(0.0){}
Sales_item(std::istream &is){ is >> *this;}
public是一个访问限定符,它的含义是公开的,任何的对象外部都可以访问,作用的范围是直到遇到下一个访问限定符。
Sales_item 与类型名称相同的函数被称为构造函数,用来在声明对象的时候调用。
:isbn(book),units_sold(0),revenue(0.0) 该部分被称为初始化列表,可以直接对成员对象或基类型机型初始化
friend std::istream& operator>>(std::istream &,Sales_item &); friend std::ostream& operator<<(std::ostream &,const Sales_item &);
两个友元函数的声明
public: Sales_item & operator+=(const Sales_item&);
+= 运算符的重载函数声明
public: double avg_price() const; bool same_isbn(const Sales_item &rhs)const{ return isbn == rhs.isbn; } std::string ISBN(){return isbn;}
3个函数的声明,其中两个函数已经进行了类内定义
public: std::string isbn; unsigned units_sold; double revenue;
3个成员变量的声明
using std::istream; using std::ostream;
两个引用声明,作用是可以再istream和ostream的前面免去std::的书写
Sales_item operator+(const Sales_item &,const Sales_item &); inline bool operator==(const Sales_item &lhs,const Sales_item &rhs){ return lhs.units_sold == rhs.units_sold && lhs.revenue == rhs.revenue && lhs.same_isbn(rhs); } inline bool operator!=(const Sales_item &lhs,const Sales_item &rhs){ return !(lhs == rhs); } inline Sales_item & Sales_item::operator +=(const Sales_item &rhs){ units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; } inline Sales_item operator+(const Sales_item &lhs,const Sales_item &rhs){ Sales_item ret(lhs); ret += rhs; return ret; } inline istream& operator>>(istream &in,Sales_item &s){ double price; in >> s.isbn >> s.units_sold >> price; if(in) s.revenue = s.units_sold * price; else s = Sales_item(); return in; } inline ostream& operator<<(ostream &out,const Sales_item &s){ out << s.isbn << "\t" <<s.units_sold << "\t" << s.revenue << "\t" << s.avg_price(); return out; } inline double Sales_item::avg_price() const{ if(units_sold) return revenue/units_sold; else return 0; }
对Sales_item的7种运算符进行了重载。
当Sales_item类型的对象作为运算符左值的时候将会调用这些重载