C++ Primer第五版_第七章习题答案(11~20)
文章目录
- 练习7.11
- 练习7.12
- 练习7.13
- 练习7.14
- 练习7.15
- 练习7.16
- 练习7.17
- 练习7.18
- 练习7.19
- 练习7.20
练习7.11
在你的Sales_data类中添加构造函数,然后编写一段程序令其用到每个构造函数。
// 头文件
#ifndef CP5_ex7_11_h
#define CP5_ex7_11_h
#include <string>
#include <iostream>
struct Sales_data
{
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() const { return bookNo; };
Sales_data& combine(const Sales_data&);
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
std::istream &read(std::istream &is, Sales_data &item)
{
double price = 0;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
std::ostream &print(std::ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue;
return os;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
Sales_data::Sales_data(std::istream &is)
{
read(is, *this);
}
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
#endif
// 主函数
#include "exercise7_11.h"
int main()
{
Sales_data item1;
print(std::cout, item1) << std::endl;
Sales_data item2("0-201-78345-X");
print(std::cout, item2) << std::endl;
Sales_data item3("0-201-78345-X", 3, 20.00);
print(std::cout, item3) << std::endl;
Sales_data item4(std::cin);
print(std::cout, item4) << std::endl;
return 0;
}
练习7.12
把只接受一个istream 作为参数的构造函数移到类的内部。
#ifndef CP5_ex7_02_h
#define CP5_ex7_02_h
#include <string>
struct Sales_data
{
std::string isbn() const { return bookNo; };
Sales_data& combine(const Sales_data&);
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
Sales_data& Sales_data::combine(const Sales_data& rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
#endif
练习7.13
使用istream构造函数重写第229页的程序。
#include "exercise7_12.h"
int main()
{
Sales_data total(std::cin);
if (!total.isbn().empty())
{
std::istream &is = std::cin;
while (is)
{
Sales_data trans(is);
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;
}
练习7.14
编写一个构造函数,令其用我们提供的类内初始值显式地初始化成员。
Sales_data() : units_sold(0) , revenue(0) { }
练习7.15
为你的 Person 类添加正确的构造函数。
#ifndef CP5_ex7_15_h
#define CP5_ex7_15_h
#include <string>
#include <iostream>
struct Person;
std::istream &read(std::istream&, Person&);
struct Person
{
Person() = default;
Person(const std::string& sname, const std::string& saddr) :name(sname), address(saddr) {}
Person(std::istream &is) { read(is, *this); }
std::string getName() const { return name; }
std::string getAddress() const { return address; }
std::string name;
std::string address;
};
std::istream &read(std::istream &is, Person &person)
{
is >> person.name >> person.address;
return is;
}
std::ostream &print(std::ostream &os, const Person &person)
{
os << person.name << " " << person.address;
return os;
}
#endif
练习7.16
在类的定义中对于访问说明符出现的位置和次数有限定吗?如果有,是什么?什么样的成员应该定义在public 说明符之后?什么样的成员应该定义在private 说明符之后?
在类的定义中对于访问说明符出现的位置和次数没有限定。每个访问说明符指定了接下来的成员的访问级别,其有效范围直到出现下一个访问说明符或者达到类的结尾处为止。
如果某个成员能够在整个程序内都被访问,那么它应该定义为 public; 如果某个成员只能在类内部访问,那么它应该定义为 private。
练习7.17
使用class 和 struct 时有区别吗?如果有,是什么?
class 和 struct 的唯一区别是默认的访问级别不同。
练习7.18
封装是何含义?它有什么用处?
将类内部分成员设置为外部不可见,而提供部分接口给外面,这样的行为叫做封装。封装隐藏了具体的实现,当我们使用某个抽象数据类型时,只需要考虑它提供什么接口操作,而不用去考虑它的具体实现。
练习7.19
在你的Person 类中,你将把哪些成员声明成public 的?哪些声明成private 的?解释你这样做的原因。
构造函数、getName()
、getAddress()
函数将设为 public。name
和 address
将设为private。函数是暴露给外部的接口,因此要设为public;而数据则应该隐藏让外部不可见。
练习7.20
友元在什么时候有用?请分别举出使用友元的利弊。
当其他类或者函数想要访问当前类的私有变量时,这个时候应该用友元。
利:与当前类有关的接口函数能直接访问类的私有变量。
弊:牺牲了封装性与可维护性。