接触过面向对象编程的朋友们都知道类中的访问控制符无非有三个,public, protected, private。
理解他就先从期望他达到的效果先说吧
Public: 使成员对于整个程序内(类内类外)都是可以访问的
Protected: 使派生类也可以访问其数据,但是又不想让其他的函数或类进行访问
Private: 只有他所在类的成员函数可以访问
在没有继承这一概念前,我们先只研究public与private就够了。
简单说,private实现的就是一种封装,让类的对象(C++primer里面叫类的用户)不能直接访问,而public让成员可以被程序的任何地方访问到。
比如:
class Base
{
public:
char a=’a’;
ChangeB(charmychar){return b= mychar };
enum num{
E_a,
E_b
}
private:
char b=’b’;
}
Base base1;
base1.a=’2’;//正确
base1.b=’2’;//错误,不能访问私有成员
base1.Show();//正确,实现了封装
Base:: num print(int tnum) //public 可以直接通过作用域访问
{
if(tnum==1) return E_a;
}
下面谈一下protected,在此之前简单说一下继承:定义相似的类型结构并以此进行建模,可以使设计的数据结构清晰易懂,同时可以实现封装和多态。简单举例来说,有一个动物的类型,里面包括老虎,狮子,猴子等,那可以把动物看做一个基类,猴子等看做一个派生类,猴子继承于动物类,可以实现更多更丰富的操作。其他有关继承概念的不在赘述~
Protected理解上就是private和public的中和,与private相似的是同样不能被类的对象(类的用户)访问,但是可以被派生类和友元访问。
下面有一个关于protected的比较难理解的结论:
派生类的成员或友元只能通过派生类对象来访问基类的受保护对象(即protected对象)。派生类对于一个基类对象中的受保护成员没有任何访问特权。
要解释这句话,首先要理解继承的机制,当一个派生类继承一个基类的时候,他就同时继承下来了基类的成员变量,也就是说这个类对象里面包含的不仅仅是自己的成员变量,还有基类的,而派生类构造的时候也要先执行基类的构造函数。
上面的”通过派生类对象来访问基类的受保护对象”意思就是可以通过基类的派生类对象访问该protected成员,因为派生类中包含基类的protected成员(继承下来的)。但是不可以直接通过访问基类对象来访问protected对象。下面举个例子:
class Base
{
protected:
char a=’a’;
}
class Son: public Base
{
voidprintBase(Base &b)
{
b.a=’1’; ///////错误,不能直接通过类访问protected成员
}
voidprintSon(Son &s)
{
s.a=’2’;
}
}
了解了类中作用域的访问控制,再看一下公有,私有,受保护的继承:
class Base
{
public:
char a=’a’;
changeB(char mychar){return b= mychar};
protected:
charb=’b’;
private:
char c=’c’;
}
struct Son1:public Base
{
CharreturnC(){ return c;} ////错误,私有变量只有类内部成员可以访问
CharreturnB(){ return b;}
CharreturnA(){ return a;}
}
struct Son2:private Base
{
charreturnC(){ return c;} ////错误,私有变量只有类内部成员可以访问
charreturnB(){ return b;} //private继承不影响派生类对基类的访问权限
charreturnA(){ return a;}
}
Son1 s1;
Son2 s2;
s1.returnA(); //正确,a在派生类Son1中是public的
s2.returnA(); //错误,a在派生类Son2中是privat的
这里要知道的是,派生类的继承访问控制影响的是派生类中成员的访问权限,不影响派生类访问基类的权限。也就是说,基类的访问控制没有变化,而派生类可以理解成下面这样~
struct Son1:public Base
{
public:
char a=’a’;
protected:
char b=’b’;
}
struct Son2:private Base
{
private:
chara=’a’;
char b=’b’;
}
所以,这时候son1的对象(用户)可以访问到a,但是son2的对象不能访问到a了。
可以把这个理解为 public继承原来的访问权限都不变,protected继承就’降级’,private就变为都是私有的。
如果细心的话可能注意到两点疑问:
1. 为什么我的Son1和Son2里面没有写char c?
2. Struct继承class如何理解?
答1:我们知道,子类根本没有权限访问父类的private,所以派生类根本就没有c这个字符串。(不过我理解可能调用基类构造函数的时候也初始化了c,然而被隐藏起来)
答2:struct和class在C++中都可以是类声明的关键字,实质上没有什么差别。唯一的区别就是struct类中的成员默认是public的。而class内的成员默认是private的。当然,我们平时也可以把struct当成c语言中的结构体来使用。
补充:假设a继承于b
1只有a公共的继承基类时,用户代码才能使用派生类向基类转换。
2 a如果是公共继承或受保护继承的,则a的派生类的成员可以使用a到b的类型转换