访问控制与继承
每个类分别控制自己的成员初始化过程,每个类还分别控制着其成员对于派生类是否可访问。
基类的protected成员只有基类和派生类成员和友元能访问,而private成员只有基类成员和友元能访问
①受保护的成员
一个类使用protected关键字声明那些派生类可以分享但是不能被其他公共访问使用的成员。protected有以下规则:
- 和私有成员类似,受保护的成员对类的对象来说是不可访问的。
- 和公有成员类似,受保护的成员对于派生类的成员和友元是可访问的。
- 派生类的成员和友元只能访问派生类对象中的基类部分的受保护成员;对于普通的基类对象中的成员不具有特殊的访问权限。
对于最后一条规则,用如下例子说明:
class A {
protected:
int _pro;
};
class B : public A {
friend void func1(B&); //能访问B::_pro
friend void func2(A&); //不能访问A::_pro
int j;
};
//正确:func1能访问B对象的private和protected成员
void func1(B &b) {
b.j = b._pro = 0;
}
//错误:func2不能访问A对象的_pro成员
void func2(A &a) {
a.j = 0;
}
②公有、私有和受保护继承
某个类对其继承而来的成员的访问权限收到两个因素影响:一是在基类中该成员的访问说明符;二是在派生类中的派生类列表中的访问说明符。
派生访问说明符包括:public(公共继承)、protected(保护继承)、private(私有继承)。访问说明符对派生类的成员(友元)能否访问器直接基类没什么影响。其目的是控制派生类对象对于基类成员的访问权限。
如下例子说明:
class Base {
public:
void _pub();
protected:
int _prot;
private:
char _priv;
};
class PubBase : public Base {
public:
//正确:派生类成员能访问protected成员
int f() {
return _prot;
}
//错误:派生类成员不能访问priv成员
char g() {
return _priv;
}
};
class PrivBase : private Base {
public:
//正确:private不影响派生类成员的访问权限
int f1() {
return _prot;
}
//错误:private不影响派生类成员的访问权限
char g1() {
return _priv;
}
}
int main() {
PubBase pb;
pb._pub(); //正确:公共继承派生类对象可以访问基类成员
cout << pb.f() << endl;
PrivBase prb;
prb._pub(); //错误:私有继承派生类对象不能访问基类成员
}
下面说明不同的继承方式的派生类对象对基类继承来的成员访问级别的影响:
- public继承:基类中的成员访问级别不变。因此,派生类对象可以访问基类中的public成员。
- protected继承:基类的public成员到派生类中变成protected的,protected和private成员变成private的。因此,派生类对象不能访问基类的成员。
- private继承:基类的public、protected和private成员到派生类中都变成private的。因此,派生类对象不能访问基类的成员。
③友元关系不能继承
就像友元关系不能传递一样,友元关系同样也不能继承,派生类的友元不能随意访问基类的成员。
如:
class A {
friend class P;
public:
int _pub;
protected:
int _prot;
private:
char _priv;
};
class B : public A {
int _j;
};
class P {
public:
//正确:P是A的友元,可以访问A对象的保护和私有成员
int f(A a) {
return a._prot;
}
//正确:对基类的访问权限由基类本身控制,即使派生类的基类部分也是如此。
int f2(B b) {
return b._prot;
}
//错误:P不是B的友元,不能访问B对象的保护和私有成员
int f3(B b) {
return b._j;
}
};
class p1 : public P {
public:
//错误:友元关系不能继承,P1不是A的友元不能访问A的保护和私有成员
int mem(A a) {
return a._prot;
}
};
④改变个别成员的可访问性
通过使用using声明可以改变派生类继承的某个名字的访问级别。如:
class A {
public:
int size() const {
return _n;
}
protected:
int _n;
}
class B : private A { //私有继承,A中的成员到B中都变成了private的
public:
using A::size; //将继承来的私有权限的size()改成公有的访问权限
protected:
using A::_n; //将继承而来私有权限的_n改成保护的访问权限
}