7.1
#include <iostream> #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0; }; int main() { using namespace std; Sales_data total; if (cin >> total.bookNo >> total.units_sold >> total.revenue) { Sales_data trans; while (cin >> trans.bookNo >> trans.units_sold >> trans.revenue) { if (total.bookNo == trans.bookNo) { total.units_sold+=trans.units_sold; total.revenue += trans.revenue; } else { cout << total.bookNo << "\t" << total.units_sold << "\t" << total.revenue << endl; total = trans; } } cout << total.bookNo << "\t" << total.units_sold << "\t" << total.revenue << endl; } else { cout << "NO data?!" << endl; return -1; } system("pause"); return 0; }
7.2
#ifndef _HEAD_H_ #define _HEAD_H_ #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0; std::string isbn(){ return bookNo; } Sales_data &combine(Sales_data &s); double avg_price()const; }; Sales_data &Sales_data::combine(Sales_data &s) { units_sold += s.units_sold; revenue += s.revenue; return *this; } double Sales_data::avg_price()const { if (units_sold) return revenue / units_sold; else return 0; } #endif
7.3
//head.h #ifndef _HEAD_H_ #define _HEAD_H_ #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0; std::string isbn(){ return bookNo; } Sales_data &combine(Sales_data &s); double avg_price()const; }; Sales_data &Sales_data::combine(Sales_data &s) { units_sold += s.units_sold; revenue += s.revenue; return *this; } double Sales_data::avg_price()const { if (units_sold) return revenue / units_sold; else return 0; } #endifmain.cpp
#include "标头.h" #include <iostream> std::istream &read(std::istream &is, Sales_data &s); std::ostream &print(std::ostream &os, const Sales_data &s); int main() { using namespace std; 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); total = trans; } } print(cout, total) << endl; } else { cerr << "No data?!" << endl; return -1; } system("pause"); return 0; } std::istream &read(std::istream &is, Sales_data &s) { is >> s.bookNo >> s.units_sold >> s.revenue; return is; } std::ostream &print(std::ostream &os, const Sales_data &s) { os << s.bookNo << "\t" << s.units_sold << "\t" << s.revenue << std::endl; return os; }
//head.h #ifndef _HEAD_H_ #define _HEAD_H_ #include <string> struct Person { std::string name="null"; std::string address = "null"; }; #endif
//head.h //需要const,为我们只是读数据,二不需要通过函数写入 #ifndef _HEAD_H_ #define _HEAD_H_ #include <string> struct Person { std::string name = "null"; std::string address = "null"; std::string getname()const{ return name; }//不允许函数修改数据成员的值 std::string getaddress()const{ return address; } }; #endif
7.6
//head.h #ifndef _HEAD_H_ #define _HEAD_H_ #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0; std::string isbn(){ return bookNo; } Sales_data &combine(const Sales_data &s); double avg_price()const; }; Sales_data &Sales_data::combine(const Sales_data &s) { units_sold += s.units_sold; revenue += s.revenue; return *this; } double Sales_data::avg_price()const { if (units_sold) return revenue / units_sold; else return 0; } std::istream &read(std::istream &is, Sales_data &s) { is >> s.bookNo >> s.units_sold >> s.revenue; return is; } std::ostream &print(std::ostream &os, const Sales_data &s) { os << s.bookNo << "\t" << s.units_sold << "\t" << s.revenue << std::endl; return os; } Sales_data add(Sales_data s1, const Sales_data &s2) { s1.combine(s2); return s1; } #endif
7.7
#include "标头.h" int main() { Sales_data total; if (read(std::cin, total)) { Sales_data trans; while (read(std::cin, trans)) { if (total.isbn() == trans.isbn()) total.combine(trans); else { print(std::cout, total) << std::endl; total = trans; } } print(std::cout, total) << std::endl; } else { std::cerr << "No data?!" << std::endl; return -1; } return 0; }
因为read需要写入到参数,改变参数的信息,而print只是输出内容,不需要变动信息,所以时const
7.9
#ifndef _HEAD_H_ #define _HEAD_H_ #include <string> #include <iostream> struct Person { std::string name = "null"; std::string address = "null"; std::string getname()const{ return name; } std::string getaddress()const{ return address; } }; std::istream &read(std::istream &is, Person &p) { is >> p.name >> p.address; return is; } std::ostream &print(std::ostream &os, const Person &p) { os << p.name << "\t" << p.address << std::endl; return os; } #endif
7.10
判断data1和data2写入数据是否发生异常?(是否成功写入数据)
7.11
#ifndef _HEAD_H_ #define _HEAD_H_ #include <iostream> #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0; Sales_data() = default; Sales_data(const std::string &s) :bookNo(s){} Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n*p){} Sales_data(std::istream &is); std::string isbn(){ return bookNo; } Sales_data &combine(const Sales_data &s); double avg_price()const; }; Sales_data &Sales_data::combine(const Sales_data &s) { units_sold += s.units_sold; revenue += s.revenue; return *this; } double Sales_data::avg_price()const { if (units_sold) return revenue / units_sold; else return 0; } Sales_data::Sales_data(std::istream &is) { read(is, *this); } std::istream &read(std::istream &is, Sales_data &s) { is >> s.bookNo >> s.units_sold >> s.revenue; return is; } std::ostream &print(std::ostream &os, const Sales_data &s) { os << s.bookNo << "\t" << s.units_sold << "\t" << s.revenue << std::endl; return os; } Sales_data add(Sales_data s1, const Sales_data &s2) { s1.combine(s2); return s1; } #endif
//main.cpp #include "标头.h" int main() { using namespace std; Sales_data item1; print(cout, item1) << endl; Sales_data item2("0-201-78345-X"); print(cout, item2) << endl; Sales_data item3("0-201-78345-X", 3, 20.00); print(cout, item3) << endl; Sales_data item4(cin); print(cout, item4) << endl; system("pause"); return 0; return 0; }
7.12
#ifndef _HEAD_H_ #define _HEAD_H_ #include <iostream> #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0; Sales_data() = default; Sales_data(const std::string &s) :bookNo(s){} Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n*p){} Sales_data(std::istream &is) { read(is, *this); } std::string isbn(){ return bookNo; } Sales_data &combine(const Sales_data &s); double avg_price()const; }; Sales_data &Sales_data::combine(const Sales_data &s) { units_sold += s.units_sold; revenue += s.revenue; return *this; } double Sales_data::avg_price()const { if (units_sold) return revenue / units_sold; else return 0; } std::istream &read(std::istream &is, Sales_data &s) { is >> s.bookNo >> s.units_sold >> s.revenue; return is; } std::ostream &print(std::ostream &os, const Sales_data &s) { os << s.bookNo << "\t" << s.units_sold << "\t" << s.revenue << std::endl; return os; } Sales_data add(Sales_data s1, const Sales_data &s2) { s1.combine(s2); return s1; } #endif
#include "标头.h" int main() { using namespace std; Sales_data total(cin); if (!total.isbn().empty()) { while (cin) { Sales_data trans(cin); if (total.isbn() == trans.isbn()) total.combine(trans); else { print(cout, total); total = trans; } } print(cout, total); } else { cerr << "No data?!" << endl; return -1; } system("pause"); return 0; }
Sales_data() :units_sold(0), revenue(0){}
#ifndef _HEAD_H_ #define _HEAD_H_ #include <string> #include <iostream> struct Person { std::string name = "null"; std::string address = "null"; Person(const std::string &n, const std::string a) :name(n), address(a){} Person(std::istream &is){ read(is, *this); } std::string getname()const{ return name; } std::string getaddress()const{ return address; } }; std::istream &read(std::istream &is, Person &p) { is >> p.name >> p.address; return is; } std::ostream &print(std::ostream &os, const Person &p) { os << p.name << "\t" << p.address << std::endl; return os; } #endif
没有特别的位置与次数限制
对外部开放的成员或者是外部可以访问的成员,都应该在public之后
只允许类对象的成员访问,这样的成员或数据应该在private之后
7.17
class默认是private,struct默认是public
7.18
封装是把已经使用过的稀有以上的装备再次变成封装状态...
封装是把类的数据成员与接口分离,实现对数据的隐藏和保护。
可以防止用户在不经意间对类数据的改变,封装好的类可以直接让别的用户直接使用,就像基本类型一样,而不需要用户对代码的修改,
7.19
name、address应该是private,数据不应该暴露在外面
getname、getaddress以是public,他们返回的都不是非const的引用或指针,无法对元素数据造成修改。
数据应该是private,不应该暴露在外
接口应该是public,提供访问的能力
7.20
friend(友元)是一种机制,允许非类成员访问类对象成员的一种方法。
优点是:
可以直接访问类的所有接口、类对象的所有成员,而不需要类名前缀(如std::)
缺点是:
破坏了类的封装、可维护性、可靠性。
7.21
#ifndef _HEAD_H_ #define _HEAD_H_ #include <iostream> #include <string> struct Sales_data { //默认是private std::string bookNo; unsigned units_sold = 0; double revenue = 0; friend std::istream &read(std::istream &is, Sales_data &s); friend std::ostream &print(std::ostream &os, const Sales_data &s); friend Sales_data add(Sales_data s1, const Sales_data &s2); public: Sales_data() = default; Sales_data(const std::string &s) :bookNo(s){} Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n*p){} Sales_data(std::istream &is) { read(is, *this); } std::string isbn(){ return bookNo; } Sales_data &combine(const Sales_data &s); double avg_price()const; }; Sales_data &Sales_data::combine(const Sales_data &s) { units_sold += s.units_sold; revenue += s.revenue; return *this; } double Sales_data::avg_price()const { if (units_sold) return revenue / units_sold; else return 0; } std::istream &read(std::istream &is, Sales_data &s) { is >> s.bookNo >> s.units_sold >> s.revenue; return is; } std::ostream &print(std::ostream &os, const Sales_data &s) { os << s.bookNo << "\t" << s.units_sold << "\t" << s.revenue << std::endl; return os; } Sales_data add(Sales_data s1, const Sales_data &s2) { s1.combine(s2); return s1; } #endif
7.22
#ifndef _HEAD_H_ #define _HEAD_H_ #include <string> #include <iostream> class Person { std::string name = "null"; std::string address = "null"; friend std::istream &read(std::istream &is, Person &p); friend std::ostream &print(std::ostream &os, const Person &p); public: Person(const std::string &n, const std::string a) :name(n), address(a){} Person(std::istream &is){ read(is, *this); } std::string getname()const{ return name; } std::string getaddress()const{ return address; } }; std::istream &read(std::istream &is, Person &p) { is >> p.name >> p.address; return is; } std::ostream &print(std::ostream &os, const Person &p) { os << p.name << "\t" << p.address << std::endl; return os; } #endif
7.23
#ifndef _HEAD_H_ #define _hEAD_H_ #include <string> #include <iostream> class Screen { typedef std::string::size_type pos; pos cursor = 0; pos height = 0, width = 0; std::string contents; public: Screen() = default; Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht*wd, c){} char get()const{ return contents[cursor]; } inline char get(pos ht, pos wd)const; Screen &move(pos r, pos c); }; char Screen::get(pos ht, pos wd)const { return contents[ht*width + wd]; } Screen &Screen::move(pos r, pos c) { cursor = r*width + c; return *this; } #endif
7.24
<pre name="code" class="cpp">#ifndef _HEAD_H_ #define _HEAD_H_ #include <string> #include <iostream> class Screen { typedef std::string::size_type pos; pos cursor = 0; pos height = 0, width = 0; std::string contents; public: Screen() = default; Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht*wd, c){} Screen(pos ht, pos wd) :height(ht), width(wd), contents(ht*wd, ' '){} // char get()const{ return contents[cursor]; } char get(pos ht, pos wd)const { return contents[ht*width + wd]; } Screen &move(pos r, pos c); }; Screen &Screen::move(pos r, pos c) { cursor = r*width + c; return *this; } #endif
7.25
可以,因为Screen类的数据成员都是带有赋值构造函数和复制构造函数的类型
7.26
//显式 Sales_data { inline double avg_price()const; //... } double Sales_data::avg_price()const { //... } //隐式 Sales_data { double avg_price()const { //... } }
#ifndef _HEAD_H_ #define _HEAD_H_ #include <string> #include <iostream> class Screen { typedef std::string::size_type pos; //string::size_type pos cursor = 0; pos height = 0, width = 0; std::string contents; void do_display(std::ostream &os)const{ os << contents; } public: Screen() = default; Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht*wd, c){} Screen(pos ht, pos wd) :height(ht), width(wd), contents(ht*wd, ' '){} // char get()const{ return contents[cursor]; } char get(pos ht, pos wd)const { return contents[ht*width + wd]; } Screen &move(pos r, pos c); Screen &set(char ch); Screen &set(pos r, pos col, char ch); Screen &display(std::ostream &os){ do_display(os); return *this; } const Screen &display(std::ostream &os)const{ do_display(os); return *this; } }; Screen &Screen::move(pos r, pos c) { cursor = r*width + c; return *this; } Screen &Screen::set(char ch) { contents[cursor] = ch; return *this; } Screen &Screen::set(pos r, pos col, char ch) { contents[r*width + col] = ch; return *this; } #endif
第二个display将打印一片X,没有#,原因是返回的不是引用,这样在myScreen调用move返回的是一个对象,这个对象已经和myScreen没关系了
7.29
修改前的输出:
XXXXXXXXXXXXXXXXXXXX#XXXX
XXXXXXXXXXXXXXXXXXXX#XXXX
修改后的输出:
XXXXXXXXXXXXXXXXXXXX#XXXX
XXXXXXXXXXXXXXXXXXXXXXXXX
7.30
优点:
可以非常明确地指出访问的是调用该函数的对象的成员,且可以在成员函数中使用与数据成员同名的形参
void show(int a) { //... cout << this->a * a << endl; //一个是show函数的变量,一个是类对象的变量 }
缺点:
有点多余
7.31
#ifndef _HEAD_H_ #define _HEAD_H_ #include <string> #include <iostream> #include <vector> class Screen; class Window_mgr { std::vector<Screen> screens{ { Screen(24, 80, ' ') } }; public: using ScreenIndex = std::vector<Screen>::size_type; void clear(ScreenIndex i); }; class Screen { friend void Window_mgr::clear(ScreenIndex i); typedef std::string::size_type pos; //string::size_type pos cursor = 0; pos height = 0, width = 0; std::string contents; void do_display(std::ostream &os)const{ os << contents; } public: Screen() = default; Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht*wd, c){} Screen(pos ht, pos wd) :height(ht), width(wd), contents(ht*wd, ' '){} // char get()const{ return contents[cursor]; } char get(pos ht, pos wd)const { return contents[ht*width + wd]; } Screen &move(pos r, pos c); Screen &set(char ch); Screen &set(pos r, pos col, char ch); Screen &display(std::ostream &os){ do_display(os); return *this; } const Screen &display(std::ostream &os)const{ do_display(os); return *this; } }; Screen &Screen::move(pos r, pos c) { cursor = r*width + c; return *this; } Screen &Screen::set(char ch) { contents[cursor] = ch; return *this; } Screen &Screen::set(pos r, pos col, char ch) { contents[r*width + col] = ch; return *this; } void Window_mgr::clear(ScreenIndex i) { Screen &s = screens[i]; s.contents = std::string(s.height*s.width, ' '); } #endif
pos类型无法找到,因为是在类里面的
修改后:
Screen::pos Screen::size()const { return height*width; }
在进行typedef前,编译器将找不到pos类型的定义
7.35
首先类里的type将覆盖类外的定义,使得setVal和initVal的返回值是double
再来就是函数定义时使用的initVal是类里的成员
typedef string Type; Type initVal(); //Type=string class Exercise { public: typedef double Type; Type setVal(Type); //Type=double Type initVal(); //Type=double private: int val; }; Type Exercise::setVal(Type parm) { //返回值是string,参数类型是double val = parm + initVal(); //使用的是Exercise的initVal,返回值是double return val;//类型不匹配 }修改后
typedef string Type; Type initVal(); class Exercise { public: typedef double Type; Type setVal(Type); Type initVal(); private: int val; }; Exercise::Type Exercise::setVal(Type parm) { val = parm + initVal(); return val;}7.36
struct X { X(int i, int j): base(i),rem(base%j){} int base, rem; //如果是rem在前,则上面的构造函数将出错,因为赋值时是按照变量声明的顺序 }
7.37
Sales_data first_item(cin); //因为是istream类型,所以等待用户输入 int main() { Sales_data next; //这个默认构造函数在初始化值Sales_data(std::string s = ""); 值为bookNo=""、cnt=0、revenue=0 Sales_data last("9-999-99999-9"); //使用了Sales_data(std::string s = ""); ,值为bookNo="9-999-99999-9"、cnt=0、revenu=0 }
Sales_data(std::istream &is = std::cin) { read(cin, *this); }
不合法,存在多个默认构造函数,因为对于Sales_data item;这样的定义来说是一样的
7.40
class Book { std::string title; std::string author; unsigned id; unsigned num; double price; public: Book() = default; Book(std::string t, std::string a = "", unsigned i = 0, unsigned n = 0, double p = 0.0) :title(t), author(a), id(i), num(n), price(p){} Book(std::istream &is); };
#ifndef _HEAD_H_ #define _HEAD_H_ #include <iostream> #include <string> struct Sales_data { std::string bookNo; unsigned units_sold = 0; double revenue = 0; friend std::istream &read(std::istream &is, Sales_data &s); friend std::ostream &print(std::ostream &os, const Sales_data &s); friend Sales_data add(Sales_data s1, const Sales_data &s2); public: Sales_data() :Sales_data("", 0, 0.0){ std::cout << "Sales_data()" << std::endl; } Sales_data(const std::string &s, unsigned n, double p) :bookNo(s), units_sold(n), revenue(n*p){ std::cout << "Sales_data(,s,n,p)" << std::endl; } Sales_data(const std::string &s) :Sales_data(s, 0, 0.0){ std::cout << "Sales_data(s)" << std::endl; } Sales_data(std::istream &is) { read(is, *this); } std::string isbn(){ return bookNo; } Sales_data &combine(const Sales_data &s); double avg_price()const; }; Sales_data &Sales_data::combine(const Sales_data &s) { units_sold += s.units_sold; revenue += s.revenue; return *this; } double Sales_data::avg_price()const { if (units_sold) return revenue / units_sold; else return 0; } std::istream &read(std::istream &is, Sales_data &s) { is >> s.bookNo >> s.units_sold >> s.revenue; return is; } std::ostream &print(std::ostream &os, const Sales_data &s) { os << s.bookNo << "\t" << s.units_sold << "\t" << s.revenue << std::endl; return os; } Sales_data add(Sales_data s1, const Sales_data &s2) { s1.combine(s2); return s1; } #endif
#ifndef _HEAD_H_ #define _HEAD_H_ #include <string> class Book { std::string title; std::string author; unsigned id; unsigned num; double price; public: Book() :Book("", 0, 0, 0.0){} Book(std::string t, std::string a = "", unsigned i = 0, unsigned n = 0, double p = 0.0) :title(t), author(a), id(i), num(n), price(p){} Book(std::istream &is); }; #endif
#ifndef _HEAD_H_ #define _HEAD_H_ class NoDefault { public: NoDefault(int){} }; class C { NoDefault nd; C() :nd(0){} }; #endif
不合法,因为NoDefault没有默认构造函数
7.45
合法,C有定义C():nd(0);默认构造函数
7.46
a 错误,因为在不定义任何构造函数的情况下将会自动提供一个默认的构造函数,该函数对所有数据成员都调用其默认构造函数
b 错误,还有带默认参数构造函数也是默认构造函数
c 错误,就算怎么无意义,也最好提供一个默认值
d 错误,在不定义任何构造函数的情况下才会自动提供一个默认的构造函数
7.47
这个看需要
好处:
可以自定义一个构造函数,参数是可以转换过来的,这样会剩下不少工作量
坏处:
无法转换,例如定义了explicit A(char *a);则只能用字符串,而无法使用string
7.48
不是explicit时 全部正确
是explicit时 item2错误
如果接受一个string的构造函数不是explicit,则都是使用接受一个string参数的构造函数
如果是explicit,那还是合法的,但是explicit是禁止进行隐式转换,从字符串转到string这不算隐式转换?
7.49
第一个string转换为Sales_data,然后传给接受Sales_data参数的构造函数
第二个string转换为Sales_data,然后Sales_data&接受
第三个string转换为Sales_data,然后const Sales_data&接受
这题....意味不明
7.50
唯一一个应该是:explicit istream &Person(istream &is);
7.51
vector是一个容器类型的类,在定义时必须制定基本类型,比如vector<int>,如果在函数接受参数时填入int变量:
void fun(vecor<int> vi);
fun(10);//如果允许这样,那就意味不明了
string不是explicit是对了,因为需要将各种类型的对象转换为字符,这样才能增加灵活性
(胡说八道一通)
7.52
"978-059........"调用bookNo对象的构造函数string(const char *)
25初始化了units_sold
15.99初始化了revenue
7.53
#ifndef _HEAD_H_ #define _HEAD_H_ class Debug { bool hw; bool io; bool other; public: constexpr Debug(bool b = true) : rt(b), io(b), other(b) { } constexpr Debug(bool r, bool i, bool o) : rt(r), io(i), other(0) { } constexpr bool any() { return rt || io || other; } void set_rt(bool b) { rt = b; } void set_io(bool b) { io = b; } void set_other(bool b) { other = b; } }; #endif
不,因为声明为constexpr的函数是需要返回一个值的
7.55
是的,因为所有数据成员都是字符类型的
7.56
与类类型相关联,而不是与类对象相关联
7.57
#ifndef _HEAD_H_ #define _HEADH_ #include <iostream> #include <string> class Account { std::string owner; double amount; static double interestRate; static double initRate(); public: void calculate(){ amount += amount*interestRate; } static double rate(){ return interestRate; } static void rate(double); }; void Account::rate(double newRate) { interestRate = newRate; } #endif
class Exampl { public: static double rate = 6.5;//错误,带初始化值的成员不能是static,改成static constexpr double rate = 6.5;或static double rate;然后再外面定义并初始化double Example::rate=6.5; static const int vecSize = 20; static vector<double> vec(vecSize);//错误,static不能带初始化值,改成static vector<double vec;然后在外面定义↓ }; //example.c #include "example.h" double Exampl::rate; vector<double> Exampl::vec;
class Exampl { public: static double rate; static const int vecSize = 20; static vector<double> vec; }; //example.c #include "example.h" double Exampl::rate=6.5; vector<double> Exampl::vec(Exampl::vecSize);
不...是躺在床上弄手机