C++Primer第五版 第7章 类 练习
7.2 访问控制与封装
练习7.2
练习7.16:在类的定义中对于访问说明符出现的位置和次数有限定吗?如果有,是什么?什么样的成员应该定义在public说明符之后?什么样的成员应该定义在private说明符之后?
答:public说明符之后定义可以在整个程序中被访问的成员;private说明符之后定义只可以被类的成员函数访问,而不能被使用该类的代码访问的成员
练习7.17:使用class和struct时有区别吗?如果有,是什么?
答:有区别;class关键字定义类的默认访问权限是private;struct关键字定义类的默认访问权限是public。
练习7.18:封装是何含义,它有什么用处?
答:封装是实现和接口的分离,它隐藏了类的实现细节;在class关键字定义的类中,我们可以使用private访问说明符封装类的实现细节。
用处:- 确保用户代码不会无意中损坏封装对象的状态。- 被封装的类具体的实现细节可以随时改变,而无需调整用户级别的代码。
练习7.19:在你的Person类中,你将把哪些成员声明成public的?哪些成员声明成private的?解释你这样做的原因。
public:构造函数,‘getName()’,‘getAddress()’;private:“mName”、“mAddress”。接口应定义为公共接口,数据不应公开给类外部。
Person.h
class Person{
public:
friend istream &read(istream &, Person &);
Person(){}
Person(string name,string address):mName(name), mAddress(address){}
Person(istream& is){
read(is,*this);
}
string getName(){
return this->mName;
}
string getAddress(){
return this->mAddress;
}
private:
string mName;//人员姓名
string mAddress;//人员地址
};
// istream &read(istream &, Person &);
ostream &print(ostream &, const Person &);
7.2.1友元
练习7.20:友元在什么时候有用?请分别列举出使用友元的利弊
答:当一个类允许其他类或者函数访问他的非公有成员,方法是令其他类或函数成为它的友元;
优点: 外部函数可以方便地使用类的成员,而不需要显示地给它们加上类名; 可以方便地访问所有非公有成员; 有时,对类的用户更容易读懂。
缺点: 减少封装和可维护性; 代码冗长,类内的声明,类外函数声明。
练习7.21:修改你的Sales_data 类使其隐藏实现的细节。你之前编写的关于Sales_data操作的程序应该继续使用,借助类的新定义重新编译改程序,确保其工作正常。
Sales_data.h
class Sales_data{
//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();
// Sales_data() = default;
Sales_data(const string &s);
Sales_data(const string &s, unsigned n, double p);
// Sales_data(istream &);
Sales_data(istream &is){
read(is, *this); //read函数的作用是从is中读取一条交易信息然后存入this对象中
}
//关于Sales_data对象的操作
string isbn() const {return bookNo;}//返回对象的isbn编号
Sales_data& combine(const Sales_data&);//将一个Sales_data对象加到另一个对象上
private:
double avg_price() const;//返回售出书籍的平均价格
string bookNo; //表示isbn编号
unsigned units_sold = 0; //书的销量
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&);
练习7.22:修改你的Person类使其隐藏实现的细节。
class Person{
public:
friend istream &read(istream &, Person &);
friend ostream &print(ostream &, const Person &);
Person(){}
Person(string name,string address):mName(name), mAddress(address){}
Person(istream& is){
read(is,*this);
}
string getName()const{
return this->mName;
}
string getAddress()const{
return this->mAddress;
}
private:
string mName;//人员姓名
string mAddress;//人员地址
};
istream &read(istream &is, Person &person)
{
return is >> person.mName >> person.mAddress;
}
ostream &print(ostream &os, const Person &person)
{
return os << person.mName << " " << person.mAddress;
}