c++ primer 第七章习题
练习7.5 应该,不需要写操作。
练习7.6 7.7
#include <iostream>
#include <string>
#include "Sales_data.h"
using namespace std;
ostream& print(ostream& os, const Sales_data& item) {
os << item.isbn() << " " << item.units_sold << " " << item.price;
return os;
}
istream& read(istream& is, Sales_data& item) {
is >> item.bookNo >> item.units_sold >> item.price;
return is;
}
Sales_data add(const Sales_data& a, const Sales_data& b) {
Sales_data sum = a;
sum.combine(b);
return sum;
}
int main()
{
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);
cout << endl;
total = trans;
}
}
print(cout, total);
cout << endl;
}
else {
cerr << "No data?!" << endl;
}
return 0;
}
#ifndef SALES_DATA_H
#define SALES_DATA_H
#include<string>
#include<iostream>
struct Sales_data {
std::string bookNo;
unsigned units_sold = 0;
double price = 0.0;
Sales_data& combine (const Sales_data& sa);
std::string isbn()const { return bookNo; }
};
Sales_data& Sales_data::combine(const Sales_data& sa) {
units_sold += sa.units_sold;
price = (price * units_sold + sa.price * sa.units_sold) / (units_sold + sa.units_sold);
return *this;
}
std::istream& read(std::istream& is, Sales_data& item);
std::ostream& print(std::ostream& os, const Sales_data& item);
Sales_data add(const Sales_data& a, const Sales_data& b);
#endif
练习7.8
read需要修改对象内容,print只需要读取。
练习7.9
#ifndef PERSON_H
#define PERSON_H
#include<string>
struct Person {
std::string name;
std::string home;
};
std::ostream& print(std::ostream& os, const Person& item) {
os << item.name << " " << item.home;
return os;
}
std::istream& read(std::istream& is, Person&item) {
is >> item.name >> item.home;
return is;
}
#endif
练习7.10
读取两条数据并判断是否正确输入。
练习7.13
int main()
{
Sales_data total(cin);
if (!total.isbn().empty()) {
Sales_data trans;
while (read(cin,trans)) {
if (total.isbn() == trans.isbn())
total.combine(trans);
else {
print(cout, total);
cout << endl;
total = trans;
}
}
print(cout, total);
cout << endl;
}
else {
cerr << "No data?!" << endl;
}
return 0;
}
练习7.14
Sales_data():bookNo(""),units_sold(0),price(0){}
练习7.15
struct Person {
std::string name;
std::string home;
Person() = default;
Person(std::string& n, std::string& h) :name(n), home(h){};
};
练习7.16 没有 类外可以访问的成员 类外不能访问的成员
练习7.17 有,默认访问权限class是private,struct是public。
练习7.18 封装是隐藏类的实现细节,能够将接口与实现分离,避免用户无意修改对象状态,修改接口实现不要更改用户代码。
练习7.20 友元可以在访问类的非公有成员。 有利于一些函数的实现,不利在于破坏类的封装。
练习7.21
class Sales_data {
friend std::istream& read(std::istream& is, Sales_data& item);
friend std::ostream& print(std::ostream& os, const Sales_data& item);
friend Sales_data add(const Sales_data& a, const Sales_data& b);
std::string bookNo;
unsigned units_sold = 0;
double price = 0.0;
public:
Sales_data() = default;
Sales_data(std::string& s) :bookNo(s){}
Sales_data(std::string& s, unsigned sold, double p) : bookNo(s), units_sold(sold), price(p) {}
Sales_data(std::istream& is) { read(is, *this); }
Sales_data& combine (const Sales_data& sa);
std::string isbn()const { return bookNo; }
};
练习7.22
class Person {
friend std::ostream& print(std::ostream& os, const Person& item);
friend std::istream& read(std::istream& is, Person&item);
private:
std::string name;
std::string home;
public:
Person() = default;
Person(std::string& n, std::string& h) :name(n), home(h){};
};
练习7.25 可以 只有string类型管理内存,其它成员都有类内初始值。
练习7.23 7.24 7.27 7.28 7.29 7.32
#include<string>
#include<iostream>
#include "Window_mgr.h"
class Screen {
public:
friend void Window_mgr::clear(ScreenIndex i);
//friend class Window_mgr;
typedef std::string::size_type pos;
Screen() = default;
Screen(pos ht, pos wd) :height(ht), width(wd), contents(ht*wd, ' ') {}
Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht*wd, c) {}
char get() const {
return contents[cursorX*width + cursorY];
}
char get(pos x, pos y) const;
Screen& set(char c);
Screen& set(pos r, pos c, char ch);
Screen& move(pos r, pos c);
Screen& display(std::ostream& os) {
do_display(os);
return *this;
}
const Screen& display(std::ostream& os) const {
do_display(os);
return *this;
}
private:
pos cursorX = 0, cursorY = 0;
pos height = 0, width = 0;
std::string contents;
void do_display(std::ostream& os) const {
os << contents;
}
};
void Window_mgr::clear(ScreenIndex i)
{
Screen &s = screens[i];
s.contents = std::string(s.height*s.width, ' ');
}
inline char Screen::get(pos x, pos y) const {
return contents[x*width + y];
}
inline Screen& Screen::set(char c) {
contents[cursorX*width + cursorY] = c;
return *this;
}
inline Screen& Screen::set(pos r, pos c, char ch) {
contents[r*width + c] = ch;
return *this;
}
Screen& Screen::move(pos r, pos c) {
cursorX = r;
cursorY = c;
return *this;
}
练习7.30 好处:不会混淆 坏处:容易接触到类内其它成员,危险。
练习7.31
class Y;
class X {
Y* y; };
class Y {
X x; }
练习7.33 pos前加Screen::
练习7.34用不了pos类型,编译错误。
练习7.35 不能重复定义类型名。
练习7.36 先初始化rem时base没有初始化。修改顺序。
练习7.37 内容与输入有关 “” 0 0 “9-999-99999-9“ 0 0
练习7.38
Sales_data(std::istream& is = std::cin) {
read(is,*this);
}
练习7.39 不行 二义性调用
练习7.41
class Sales_data {
// 不变
public:
Sales_data(std::string s, unsigned sold, double p) : bookNo(s), units_sold(sold), price(p) {
std::cout << "3 parameters." << std::endl;
}
Sales_data() :Sales_data("", 0, 0){
std::cout << "0 parameters." << std::endl;
}
Sales_data(std::string s) :Sales_data(s, 0, 0){
std::cout << "1 parameters" << std::endl;
}
Sales_data(std::istream& is) :Sales_data() {
read(is, *this);
std::cout << "istream parameter" << std::endl;
}
//不变
};
练习7.43
C::C():C_member(0) {}
练习7.44 不合法 没有合适的默认构造函数。
练习7.45 合法,有对应默认构造函数。
练习7.46 (a) T (b) T (c) F (d) F 类内初始值
练习7.47 是 不能使用拷贝初始化语句用const char*构造sales_data 对象。
练习7.48 使用有一个string参数的构造函数。
隐式转换为string后使用构造函数。
练习7.49 (a) 正确,生成临时对象并相加。 (b) 错误,不能把临时对象赋值给引用类型 (c)正确
练习7.51 string需要能够使用const char*通过=进行赋值构造。
练习7.52 存在类内初始值。
练习7.54 不应该, 不是只有一个return语句。
练习7.55 没有constexpr的构造函数。
练习7.56 类内带static声明的。 独立于对象存在。
生命周期不同,静态成员存在整个程序;独立于对象存在,可以是不完全类型;可以作为成员函数默认实参。
练习7.58 非const或者非constexpr的静态数据成员需要在类外定义。