练习

7.16

无,类的接口定义在public说明符之后,类的实现细节定义在private说明符之后。

7.17

有。类成员的默认访问权限不同。class的类成员默认为private,struct的则默认为public。

通常来说,当我们希望定义的类的所有成员是public的时候就用struct。

7.18

p242

7.19

【友元】

练习

7.20

声明的类外函数需要直接引用类内的私有成员的时候要用到友元函数。

设计原因:并非所有的、与某个类相关的函数都适合声明成那个类的成员函数,例如书上的add(obj, obj);

利弊:不详。。。

7.21

遇到问题了。已经声明成友元函数还是不能访问私有数据???

#include <iostream>
#include <string>
using namespace std; // Sales_data.h
class Sales_data {
friend Sales_data add(const Sales_data&, const Sales_data&);
friend ostream &print(ostream&, const Sales_data&);
friend istream &read(iostream&, Sales_data&);
public:
Sales_data() = default;
Sales_data(const string &s): bookNo(s) {}
Sales_data(const string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) {}
Sales_data(istream&);
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price() const;
private:
string bookNo;
unsigned units_sold = ;
double revenue = 0.0;
};
// Sales_data的非成员接口函数
Sales_data add(const Sales_data&, const Sales_data&);
ostream &print(ostream&, const Sales_data&);
istream &read(iostream&, Sales_data&); // Sales_data.cpp
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this;
}
istream &read(istream &is, Sales_data &item)
{
double price = ;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
ostream &print(ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
return os;
}
double Sales_data::avg_price() const {
if (units_sold)
return revenue/units_sold;
else
return ;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
Sales_data::Sales_data(istream &is)
{
read(is, *this);
} // main.cpp
int main()
{
Sales_data data1; // default
Sales_data data2("ISOD233");
Sales_data data3("ISOD233", , 22.5);
Sales_data data4(cin); print(cout, data1) << endl;
print(cout, data2) << endl;
print(cout, data3) << endl;
print(cout, data4) << endl;
/* output:
0 0
ISOD233 0 0 0
ISOD233 3 67.5 22.5
DASD23 4 88 22
*/
return ;
}

编译结果如下:

$ g++ prog1.cpp -std=c++
prog1.cpp: In function 'std::istream& read(std::istream&, Sales_data&)':
prog1.cpp::: error: 'std::__cxx11::string Sales_data::bookNo' is private
string bookNo;
^
prog1.cpp::: error: within this context
is >> item.bookNo >> item.units_sold >> price;
^
prog1.cpp::: error: 'unsigned int Sales_data::units_sold' is private
unsigned units_sold = ;
^
prog1.cpp::: error: within this context
is >> item.bookNo >> item.units_sold >> price;
^
prog1.cpp::: error: 'double Sales_data::revenue' is private
double revenue = 0.0;
^
prog1.cpp::: error: within this context
item.revenue = price * item.units_sold;
^
prog1.cpp::: error: 'unsigned int Sales_data::units_sold' is private
unsigned units_sold = ;
^
prog1.cpp::: error: within this context
item.revenue = price * item.units_sold;

已改正:

#include <iostream>
#include <string>
using namespace std; // Sales_data.h
class Sales_data {
friend Sales_data add(const Sales_data&, const Sales_data&);
friend ostream &print(ostream&, const Sales_data&);
friend istream &read(istream&, Sales_data&);
public:
Sales_data() = default;
Sales_data(const string &s): bookNo(s) {}
Sales_data(const string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) {}
Sales_data(istream&);
std::string isbn() const { return bookNo; }
Sales_data& combine(const Sales_data&);
double avg_price() const;
private:
string bookNo;
unsigned units_sold = ;
double revenue = 0.0;
};
// Sales_data的非成员接口函数
Sales_data add(const Sales_data&, const Sales_data&);
ostream &print(ostream&, const Sales_data&);
istream &read(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;
}
istream &read(istream &is, Sales_data &item)
{
double price = ;
is >> item.bookNo >> item.units_sold >> price;
item.revenue = price * item.units_sold;
return is;
}
ostream &print(ostream &os, const Sales_data &item)
{
os << item.isbn() << " " << item.units_sold << " " << item.revenue << " " << item.avg_price();
return os;
}
double Sales_data::avg_price() const {
if (units_sold)
return revenue/units_sold;
else
return ;
}
Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
{
Sales_data sum = lhs;
sum.combine(rhs);
return sum;
}
Sales_data::Sales_data(istream &is)
{
read(is, *this);
} // main.cpp
int main()
{
Sales_data data1; // default
Sales_data data2("ISOD233");
Sales_data data3("ISOD233", , 22.5);
Sales_data data4(cin); print(cout, data1) << endl;
print(cout, data2) << endl;
print(cout, data3) << endl;
print(cout, data4) << endl;
/* output:
0 0
ISOD233 0 0 0
ISOD233 3 67.5 22.5
DASD23 4 88 22
*/
return ;
}

声明多写了一个o。

7.22

#include <iostream>
#include <string>
using namespace std; // Person.h
class Person {
friend istream &read(istream &is, Person &p);
public:
Person() = default;
Person(const string &name): name(name) {}
Person(const string &name, const string &address): name(name), address(address) {}
Person(istream&);
string getName() const { return name; }
string getAddress() const { return address; }
private:
string name;
string address;
};
istream &read(istream&, Person&);
ostream &print(ostream&, const Person&); // Person.cpp
istream &read(istream &is, Person &p)
{
is >> p.name >> p.address;
return is;
}
ostream &print(ostream &os, const Person &p)
{
os << p.getName() << " " << p.getAddress();
return os;
}
Person::Person(istream &is)
{
read(is, *this);
} // main.cpp
int main()
{
Person p1;
Person p2("xklf");
Person p3("llyy", "china");
Person p4(cin);
print(cout, p1) << endl;
print(cout, p2) << endl;
print(cout, p3) << endl;
print(cout, p4) << endl;
return ;
}

【c++ primer, 5e】访问控制与封装的更多相关文章

  1. 【c++ primer, 5e】函数声明 & 分离式编译

    p186~p188: 函数声明1.函数只能定义一次,但是可以声明多次. 2.函数的接口:返回类型 + 函数名 + 形参类型 3.为什么要在头文件中进行函数声明???在源文件中定义?暂时理解到,这么做可 ...

  2. 【c++ primer, 5e】【函数基础】

    p182~p185: 函数1.在调用函数和执行return语句的同时,也发生了控制权的转移. 2.函数返回值不能是一个数组.(但是可以返回一个包含数组的对象,或者指向数组的指针) 3.重要概念:名字的 ...

  3. 【c++ primer, 5e】【try语句块】

    p172~p177:c++的try语句块和异常处理: 1.通常,与用户交互的代码和对象相加(底层的代码)是分离开的,异常由与用户交互的代码处理(底层代码抛出异常就可以了). 2.C++的runtime ...

  4. 【c++ primer, 5e】构造函数 & 拷贝、赋值和析构

    [构造函数] 1.构造器就是创建对象时被调用的代码. 2.如果没有自定义构造器,那么编译器将自动合成一个默认的无参构造器. 3.自定义的构造器不允许加const,所创建const的对象只有在构造器代码 ...

  5. 【c++ primer, 5e】定义类相关的非成员函数

    练习 7.6 & 7.7 #include <iostream> #include <string> using namespace std; // Sales_dat ...

  6. 【c++ primer, 5e】设计Sales_data类 & 定义改进的Sales_data类

    [设计Sales_data类] 1.考虑Sales_data类应该有那些接口. isbn.combine.add.read.print... 2.考虑如何使用这些接口. Sales_data tota ...

  7. 【c++ primer, 5e】函数指针

    简单的示例: #include <iostream> using namespace std; int sum(int x, int y) { return x + y; } int ma ...

  8. 【c++ primer, 5e】函数匹配

    练习 6.49 候选函数:与所调用的函数的名字相同的函数的集合. 可行函数:给候选函数加上参数数量.参数类型的约束所得到的函数的集合. 6.50 a 3.4可行,二义匹配 b 2.4可行,2是最佳匹配 ...

  9. 【c++ primer, 5e】特殊用途语言特性

    [默认实参] 1.注意点:函数的默认实参可以在函数的声明中添加,但是后续声明只能添加默认参数而不能改变先前声明的默认参数.(函数的声明通常是定义在头文件上的,多次声明同一个函数是合法的) 2.默认实参 ...

随机推荐

  1. 修改了JS代码,刷新网页后,加载的JS还是原来旧的?

    本地修改JS脚本后,刷新网页看一下修改后的执行效果,结果调试显示加载的JS还是原来旧的,反复刷新均无效,郁闷! 解决办法:清理一下浏览器缓存(长经验了!)     Ctrl+Shift+Del 清除G ...

  2. poj 3249(bfs+dp或者记忆化搜索)

    题目链接:http://poj.org/problem?id=3249 思路:dp[i]表示到点i的最大收益,初始化为-inf,然后从入度为0点开始bfs就可以了,一开始一直TLE,然后优化了好久才4 ...

  3. 为什么要使用docker

    1. 为什么要使用Docker Docker容器虚拟化的好处 Docker项目的发起人和Docker Inc.的CTO Solomon Hykes认为,Docker在正确的地点.正确的时间顺应了正确的 ...

  4. SQL Server系统函数简介[转]

    一.字符转换函数1.ASCII()返回字符表达式最左端字符的ASCII 码值.在ASCII()函数中,纯数字的字符串可不用‘’括起来,但含其它字符的字符串必须用‘’括起来使用,否则会出错.2.CHAR ...

  5. CommonJS和AMD/CMD

    JS中的模块规范(CommonJS,AMD,CMD) 一,CommonJS NodeJS是CommonJS规范的实现,webpack也是以CommonJS的形式来书写. 在浏览器环境下,没有模块也不是 ...

  6. JZOJ.5279【NOIP2017模拟8.15】香港记者

    Description

  7. java jdk 1.6 下载

    http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase6-41940 ...

  8. 禁用chrome默认打印框直接打印

    在做web打印的时候 重要弹出一个对话框选择打印机等等, 比较影响操作, 经过一番谷歌终于找到了解决方案 在桌面的chrome 图标 右键 打开属性对话框 在目标 添加  --kiosk-printi ...

  9. mac下面安装mysql

    参考http://www.cnblogs.com/lakeslove/p/6280404.html 关于msyql5.7,安装时最大的改变就是有了一个默认密码 我安装的是mysql-5.7.17-ma ...

  10. [LintCode] 第k大元素

    基于快速排序: class Solution { public: /* * param k : description of k * param nums : description of array ...