3.2 访问控制与安装
我们使用 访问说明符(access specifiers) 加强类的封装性:
- 定义在 public 说明符之后的成员在整个程序内可被访问,public成员定义类的接口
- 定义在 private 说明符之后的成员可以被类的成员函数访问,但是不能被使用该类的代码访问,private部分封装(即隐藏)了类的实现细节。
class Sales_data {
public:
// 添加了访问说明符
Sales_data() = default;
Sales_data(const std::string &s, unsigned n, double p) :
bookNo(s), units_sold(n), revenue(p*n) { }
Sales_data(const std::string &s) : bookNo(s) { }
Sales_data(std::istream&);
std::string isbn() const { return bookNo; }
Sales_data &combine(const Sales_data&);
private:
// 添加了访问说明符
double avg_price() const
{ return units_sold ? revenue/units_sold : 0; }
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
一个类可以包含0个或多个访问说明符,而且对于某个访问说明符能出现多少次也没有严格限定。每个访问说明符指定了接下来的成员的访问级别,其有效范围直到出现下一个访问说明符或到达类的结尾处为止。
使用class
或struct
关键字¶
二者的唯一区别是,struct
和class
的默认访问权限不太一样。
类可以在它的第一个说明符之前定义成员,若是struct则定义在第一个说明符之前的成员是public的;若是class,反之。
3.2.1 友元¶
class Sales_data {
// 为 Sales_data的非成员函数所做的友元声明
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::istream& read(std::istream&, Sales_data&);
friend std::ostream& print(std::ostream&, const Sales_data&);
// 其他成员及访问说明符与之前一致
public:
// 添加了访问说明符
Sales_data() = default;
Sales_data(const std::string &s, unsigned n, double p) :
bookNo(s), units_sold(n), revenue(p*n) { }
Sales_data(const std::string &s) : bookNo(s) { }
Sales_data(std::istream&);
std::string isbn() const { return bookNo; }
Sales_data &combine(const Sales_data&);
private:
// 添加了访问说明符
double avg_price() const
{ return units_sold ? revenue/units_sold : 0; }
std::string bookNo;
unsigned units_sold = 0;
double revenue = 0.0;
};
// Sales_data接口的非成员组成部分的声明
Sales_data add(const Sales_data&, const Sales_data&);
std::istream& read(std::istream&, Sales_data&);
std::ostream& print(std::ostream&, const Sales_data&);
类允许其他类或者函数访问它的非公有成员,方法是令其他类或者函数成为它的 友元(friend)。如果类想把一个函数作为它的友元,只需要增加一条以 friend
关键字开始的函数声明语句即可。
友元声明只能出现在类定义的任何地方,友元不是类的成员也不受它躲在区域访问控制级别的约束。
友元的声明:
友元的声明仅仅指定了访问的权限,我们必须在友元声明之外再专门对函数进行一次声明。
为了使友元对类的用户可见,我们通常把友元的声明与类本身放置在同一个头文件中(类的外部)。