1.类成员的访问说明符
在C++语言中,访问说明符(access specifiers)被用来加强类的封装性。通过访问说明符,类的设计者可以规定哪些成员变量和成员函数是内部外部都可见的,哪些成员变量和成员函数是只能在类内部使用的,外部是不可见的。public说明符合private说明符就起了这样的区分作用。《C++ Primer》P240页写到:
- 定义在public说明符之后的成员在整个程序内可以被访问,public成员定义类的接口。
- 定义在private说明符之后的成员可以被类的成员函数访问,但是不能被使用该类的代码访问,private部分封装了(即隐藏)类的实现细节。
简单一点说,public和private的区别就在于是否可以通过实例化的类,也就是对象来访问。
1 #include <iostream> 2 3 using namespace std; 4 5 class Sales_data{ 6 public: 7 Sales_data() =default; 8 Sales_data(const std::string&s,unsigned n ,double p): 9 bookNo(s),units_sold(n),revenue(p*n){} 10 Sales_data(const std::string &s):bookNo(s){} 11 Sales_data(std::istream&); 12 std::string isbn()const{return bookNo;} 13 Sales_data &combine(const Sales_data&); 14 15 private: 16 double avg_price()const 17 { return units_sold?revenue/units_sold:0;} 18 std::string bookNo; 19 unsigned units_sold = 0; 20 double revenue = 0.0; 21 }; 22 int main() 23 { 24 Sales_data data1("123434"); 25 cout<<data1.isbn()<<endl; //正确:isbn是public的,可以被该类的代码访问 26 cout<<data1.bookNo<<endl; // 错误:bookNo是私有属性,不能被使用该类的代码(该类的对象访问) 27 return 0; 28 }
一般在面向对象中,方法总是public的,因为方法相当于接口,用户要使用接口实现功能呢;变量总是私有的,这样可以避免用户对类进行修改。
友元:
如果其他类或者函数需要访问它的非公有成员, 那就要让这些类和函数成为它的友元(friend)。具体做法是在类内部添加一条以friend关键字开头的函数声明语句:
1 class Sales_data{ 2 friend Sales_data add(const Sales_data&,const Sales_data&); 3 ... 4 }; 5 6 Sales_data add(const Sales_data&,const Sales_data&); //友元函数在类的外部声明和定义
友元函数不能被继承和传递。
protected访问说明符:
再引入继承的概念之后,我们希望类的一些属性可以被子类访问,但是还是不能被公共访问,这时候要用到protected访问说明符。
- 和私有成员类似,受保护的成员对于类的用户来说是不可访问的。
- 和公有成员类似,受保护的成员对于派生类的成员和友元来说是可访问的。
- 派生类的成员或友元只能通过派生类对象来访问基类的受保护成员。派生类对于一个基类对象中的受保护成员没有任何访问权限。
访问控制和继承
派生类对其基类成员的访问权限受到两方面的影响,一是基类中成员的访问说明符,二是派生类列表中的访问说明符。其中,基类成员的访问说明符影响派生类内部的成员函数(新增)对基类成员的访问权限,派生类列表的访问说明符影响派生类对象对基类成员的访问。
1. 基类中成员的访问说明符
基类成员中的访问说明符影响派生类成员的访问权限
public成员:可以被派生类访问
protected成员:可以被派生类访问
private成员:不可以被派生类访问
2. 派生类列表中的访问说明符
派生类说明符对于派生类的成员函数(及友元)能否访问其直接基类的成员没有影响,它控制的是派生类用户(对象)对基类成员的访问。
public继承:基类的共有成员和保护成员作为派生类成员时,保持原有状态。
protected继承:基类的所有公有成员和私有成员都成为派生类的保护成员,只能被它的派生类成员和友元函数访问。
private继承:基类的所有公有成员和保护成员都作为派生类的私有成员,不能被它的派生类的派生类访问,即只能由派生类本身访问。
总结
基类成员 | public | protected | private | public | protected | private | public | protected | private |
继承方式 | public | protected | private | ||||||
派生类内部 | public | protected | 不可见 | protected | protected | 不可见 | private | private | 不可见 |
派生类外部 | 可见 | 不可见 | 不可见 | 不可见 | 不可见 | 不可见 | 不可见 | 不可见 | 不可见 |