【c++ primer, 5e】设计Sales_data类 & 定义改进的Sales_data类
【设计Sales_data类】
1、考虑Sales_data类应该有那些接口。
isbn、combine、add、read、print...
2、考虑如何使用这些接口。
Sales_data total; if (read(cin, total)) { Sales_data trans; while (read(cin, trans)) { if (total.isbn() == trans.isbn()) total.combine(trans); else { print(cout, total) << endl; total = trans; } } print(cout, total) << endl; } else { cerr << "No data?!" << endl; }
练习
7.1
#include <iostream> #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double price = 0.0; double revenue = 0.0; }; int main() { Sales_data total; if (std::cin >> total.bookNo >> total.units_sold >> total.price) { Sales_data trans; while (std::cin >> trans.bookNo >> trans.units_sold >> trans.price) { if(total.bookNo == trans.bookNo) { total.units_sold += trans.units_sold; } else { std::cout << total.bookNo << " " << total.units_sold << " " << total.price << std::endl; total = trans; } } std::cout << total.bookNo << " " << total.units_sold << " " << total.price << std::endl; } else { std::cerr << "No data?" << std::endl; return -1; } return 0; }
【定义改进的Sales_data类】
struct Sales_data { // public部分,对象看起来是怎么样的。 std::string isbn() const { return bookNo; } // inline function Sales_data& combine(const Sales_data&); double avg_price() const; // private部分,数据成员。 std::string bookNo; unsigned units_sold = 0; double revenue = 0.0; }; // Sales_data的非成员接口函数 Sales_data add(const Sales_data&, const Sales_data&); std::ostream &print(std::ostream&, const Sales_data&); std::istream &read(std::istream&, Sales_data&);
this与const成员函数
1、可以通过return *this;返回对象本身。
2、在某个类的成员函数声明(定义)的参数列表之后加上const,意味着该函数所使用的隐式参数T *const this被修改为const T *const this,它们之间的区别在于,前者无法持有常量对象,而后者既可以持有常量对象也可以持有非常量对象。
因此,const成员函数的引入提高了函数的灵活性,使得const obj可以调用相应的常量成员函数。
练习
7.2 & 7.3
#include <iostream> #include <string> using namespace std; // Sales_data.h struct Sales_data { // public部分,对象看起来是怎么样的。 std::string isbn() const { return bookNo; } // inline function Sales_data& combine(const Sales_data&); double avg_price() const; // private部分,数据成员。 std::string bookNo; unsigned units_sold = 0; double revenue = 0.0; }; // Sales_data的非成员接口函数 Sales_data add(const Sales_data&, const Sales_data&); std::ostream &print(std::ostream&, const Sales_data&); std::istream &read(std::istream&, Sales_data&); // Sales_data.cpp Sales_data& Sales_data::combine(const Sales_data &rhs) { units_sold += rhs.units_sold; revenue += rhs.revenue; return *this; } // main.cpp int main() { Sales_data total; if (std::cin >> total.bookNo >> total.units_sold) { Sales_data trans; while (std::cin >> trans.bookNo >> trans.units_sold) { if (total.isbn() == trans.isbn()) total.combine(trans); else { std::cout << total.bookNo << " " << total.units_sold << " " << std::endl; total = trans; } } std::cout << total.bookNo << " " << total.units_sold << " " << std::endl; } else { cerr << "No data?!" << endl; } return 0; }
7.4
#include <iostream> #include <string> using namespace std; // Person.h struct Person { string name; string address; } // Person.cpp // main.cpp
7.5
应该加const。因为不论是常量对象还是非常量对象都有权访问自己的姓名和住址,这个操作并没有涉及改变对象的数据成员。
什么时候不加const?调用者不希望常量对象调用该函数的时候就不加const,例如书上的combine函数。
当函数只涉及“访问”而不涉及“改变”的时候加const,当函数涉及“改变”的时候不加const。