【c++ primer, 5e】访问控制与封装
练习
7.16
无,类的接口定义在public说明符之后,类的实现细节定义在private说明符之后。
7.17
有。类成员的默认访问权限不同。class的类成员默认为private,struct的则默认为public。
通常来说,当我们希望定义的类的所有成员是public的时候就用struct。
7.18
p242
【友元】
练习
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】访问控制与封装的更多相关文章
- 【c++ primer, 5e】函数声明 & 分离式编译
p186~p188: 函数声明1.函数只能定义一次,但是可以声明多次. 2.函数的接口:返回类型 + 函数名 + 形参类型 3.为什么要在头文件中进行函数声明???在源文件中定义?暂时理解到,这么做可 ...
- 【c++ primer, 5e】【函数基础】
p182~p185: 函数1.在调用函数和执行return语句的同时,也发生了控制权的转移. 2.函数返回值不能是一个数组.(但是可以返回一个包含数组的对象,或者指向数组的指针) 3.重要概念:名字的 ...
- 【c++ primer, 5e】【try语句块】
p172~p177:c++的try语句块和异常处理: 1.通常,与用户交互的代码和对象相加(底层的代码)是分离开的,异常由与用户交互的代码处理(底层代码抛出异常就可以了). 2.C++的runtime ...
- 【c++ primer, 5e】构造函数 & 拷贝、赋值和析构
[构造函数] 1.构造器就是创建对象时被调用的代码. 2.如果没有自定义构造器,那么编译器将自动合成一个默认的无参构造器. 3.自定义的构造器不允许加const,所创建const的对象只有在构造器代码 ...
- 【c++ primer, 5e】定义类相关的非成员函数
练习 7.6 & 7.7 #include <iostream> #include <string> using namespace std; // Sales_dat ...
- 【c++ primer, 5e】设计Sales_data类 & 定义改进的Sales_data类
[设计Sales_data类] 1.考虑Sales_data类应该有那些接口. isbn.combine.add.read.print... 2.考虑如何使用这些接口. Sales_data tota ...
- 【c++ primer, 5e】函数指针
简单的示例: #include <iostream> using namespace std; int sum(int x, int y) { return x + y; } int ma ...
- 【c++ primer, 5e】函数匹配
练习 6.49 候选函数:与所调用的函数的名字相同的函数的集合. 可行函数:给候选函数加上参数数量.参数类型的约束所得到的函数的集合. 6.50 a 3.4可行,二义匹配 b 2.4可行,2是最佳匹配 ...
- 【c++ primer, 5e】特殊用途语言特性
[默认实参] 1.注意点:函数的默认实参可以在函数的声明中添加,但是后续声明只能添加默认参数而不能改变先前声明的默认参数.(函数的声明通常是定义在头文件上的,多次声明同一个函数是合法的) 2.默认实参 ...
随机推荐
- jQuery多项选项卡的实现
请勿盗版.转载请加上出处http://blog.csdn.net/yanlintao1 请勿盗版,转载请加上出处http://blog.csdn.net/yanlintao1 css样式: @CHAR ...
- Openstack(Kilo)安装系列之neutron(九)
控制节点 Before you configure the OpenStack Networking (neutron) service, you must create a database, se ...
- java锁和同步
Java 语言设计中的一大创新就是:第一个把跨平台线程模型和锁模型应用到语言中去,Java 语言包括了跨线程的关键字synchronized 和 volatile,使用关键字和java类库就能够简单的 ...
- Ubuntu使用yah3c连接校园网
虽然网上有,但是我还是把这当作学习的一个过程记录下来,以备不时之需. 刚开始总是以为要上校园网就要用inode,所以总是百度谷歌不到方法,后来才知道yah3c不等同于inode,二者应该是并行的关系. ...
- 【SR】论文资源相关
1. Anchored Neighborhood Regression for Fast Example-Based Super-Resolution Radu Timofte, Vincent De ...
- 【转】使用UMDH查找内存泄漏
转载出处:http://blog.csdn.net/phiger/article/details/1932141 Umdh 是 Debugging Tools for Windows 里面的一个工具, ...
- cocos3.x 接入微信无法调用回调函数onResp的问题
要想顺利调用必须保证一下几点: 1.WXEntryActivity的包名必须正确,格式为你的APK包名+wxapi.WXEntryActivity(注意:是apk包名,而不是org.cocos2dx. ...
- 170208、用Navicat自动备份mysql数据库
数据库备份很重要,很多服务器经常遭到黑客的恶意攻击,造成数据丢失,如果没有及时备份的话,后果不堪设想. 一:备份的目的: 做灾难恢复:对损坏的数据进行恢复和还原 需求改变:因需求改变而需要把数据还原到 ...
- Exchange 2016 系统要求
Exchange 2016 和早期版本的 Exchange Server 共存方案 Exchange 2016支持混合部署方案 Exchange 2016 的网络和目录服务器要求 目录服务体系结构: ...
- javascript数组中的方法
数组中的方法 今天我们来说一下,对数组进行操作的几种方法: //添加 a=[];//空数组 a[0]="我是第一个"; a[2]="我是第三个"; ...