【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.默认实参 ...
随机推荐
- 【BZOJ】2020: [Usaco2010 Jan]Buying Feed, II (dp)
http://www.lydsy.com/JudgeOnline/problem.php?id=2020 和背包差不多 同样滚动数组 f[j]表示当前位置j份食物的最小价值 f[j]=min(f[j- ...
- 广义高斯分布(GGD)
广义高斯分布(GGD)-Generalized Gaussian Distribution 广义高斯分布及其在图像去噪的应用_百度文库 https://wenku.baidu.com/view/2b8 ...
- PatternSyntaxException:Syntax error in regexp pattern
Caused by: java.util.regex.PatternSyntaxException: Syntax error in regexp pattern near index 1: ...
- Qt 配置文件QSettings读取以及中文问题
QSettings settings("xxxx.ini",QSettings::IniFormat);settings.setIniCodec(QTextCodec::codec ...
- iOS-地图开发 Plist文件设置权限
解决办法: 在.Plist文件中添加 <key>NSLocationUsageDescription</key> <string>请点击“好”以允许访问. 若不允许 ...
- 高性能javascript 文件加载阻塞
高性能javascript javascript脚本执行过程中会中断页面加载,直到脚本执行完毕,此操作阻塞了页面加载,造成性能问题. 脚本位置和加载顺序:如果将脚本放在head内,那么再脚本执行完 ...
- A1261. happiness(吴确)[二元组暴力最小割建模]
A1261. happiness(吴确) 时间限制:500ms 内存限制:512.0MB 总提交次数:158 AC次数:72 平均分:56.71 将本题分享到: 查看 ...
- C#中遍历ArrayList的三种方法
using System; using System.Collections; using System.Linq; using System.Text; namespace ArrayListDem ...
- 《JAVA多线程编程核心技术》 笔记:第二章:对象及变量的并发访问
一.基本概念1.安全的变量和不安全的变量2.脏读的理解3.锁重入:4.锁释放5.死循环:二.synchronized 的理解:三.synchronized 同步方法3.1 同步方法不具有继承性.3.2 ...
- 【Python之路】第十八篇--MySQL(一)
一.概述 1.什么是数据库 ? 答:数据的仓库. 2.什么是 MySQL.Oracle.SQLite.Access.MS SQL Server等 ? 答:他们均是一个软件,都有两个主要的功能: a. ...