访问控制与封装
文章目录
- 访问说明符:
- 友元:
- 封装好处:
class Sales_data{public://作为接口的一部分,构造函数和部分成员函数isbn,combine紧跟在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://数据成员和作为实现部分的函数跟在private说明符之后。double avg_price() const {return units_sold ? revenue/units_sold : 0;}std::string bookNo;unsigned units_sold = 0;double revenue = 0.0;
};
访问说明符:
- public说明符:定义在public后的成员在整个程序内可被访问,public成员定义类的接口。
- private说明符:定义在private后的成员可以被类的成员函数访问,但是不能被使用该类的代码访问,private成员定义类的接口。
class关键字和struct关键字:
- 这两个关键字都可以用来定义类。
- 区别:struct和class的默认访问权限不同。
- 使用struct关键字,定义在第一个访问说明符之前的成员是public的。
- 使用class关键字,定义在第一个访问说明符之前的成员是private的。
- 一般希望定义类的所有成员是public的,用struct;全是private的用class。
友元:
class Sales_data {//为sales_data的非成员函数所做的友元声明。
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::ostream &print(std::ostream&, const Sales_data&);
friend std::istream &read(std::istream&, Sales_data&);
public:// constructorsSales_data() = default;Sales_data(const std::string &s): bookNo(s) { }Sales_data(const std::string &s, unsigned n, double p):bookNo(s), units_sold(n), revenue(p*n) { }Sales_data(std::istream &);// operations on Sales_data objectsstd::string isbn() const { return bookNo; }Sales_data& combine(const Sales_data&);double avg_price() const;
private:std::string bookNo;unsigned units_sold = 0;double revenue = 0.0;
};// nonmember Sales_data interface functions
//友元声明仅仅指定了访问权限,如果我们希望用户能调用友元函数,还需要在友元声明之外再专门对函数进行一次声明。
Sales_data add(const Sales_data&, const Sales_data&);
std::ostream &print(std::ostream&, const Sales_data&);
std::istream &read(std::istream&, Sales_data&);
类还可能有非成员函数,函数在概念上属于类,但是不定义在类中,则它一般应与类声明在同一个头文件内。这里的add,print,read函数就是非成员函数。
既然Sales_data数据成员是private的,那我们add,print,read函数就无法正常编译了。
类可以允许其他类或者函数访问它的非公有成员,方法就是令其他类或者函数称为它的友元。只需增加一条以friend关键字开始的函数声明语句。
friend Sales_data add(const Sales_data&, const Sales_data&);
friend std::ostream &print(std::ostream&, const Sales_data&);
friend std::istream &read(std::istream&, Sales_data&);
友元声明只能出现在类的内部,但是具体位置不限。
封装好处:
- 被封装的类的具体实现细节可以随意改变,无需调整用户级别的代码。
- 确保用户代码不会无意间破坏封装对象的状态。