Java 中有四种访问控制:public、protected、default、private,它们的使用范围可以用下面一张表概括:
整个结构还是比较简单的,从类内部到本包到子类到外部包权限越来越小,比较好理解也比较好记忆。但是在 C++中访问控制要复杂很多,因为不仅有属性和方法的访问控制,还有继承时的派生列表访问说明符。今天我们着重了解访问控制。
在 Java 中我们一般默认子类可以访问父类的 protected,但是 C++中要更复杂些。它有三个特征:
怎么理解第三点呢?举个例子:
class Base{
protected:
int num;
}
class Sub:public Base{
friend void set(Sub&);
friend void set(Base&);
int i;
}
void set(Sub& sub){
sub.i = sub.num = 0;//正确,可以访问基类和派生类的成员
}
void set(Base &base){
base.num = 0;//错误,不能访问基类的成员
}
为什么要这样设计呢?如果派生类的友元可以直接访问基类的受保护成员,那么我们对任何类,只要设计它的子类,在子类的友元函数中就可以访问基类受保护的成员了,破坏了设计访问控制的目的,这一点比 Java 要严谨一些,任何访问控制都会被反射虐的体无完肤。
所以这里的结论是:派生类的成员和友元只能访问派生类对象中的基类部分的受保护成员,对于普通的基类对象中的成员不具有特殊的访问权限。
派生访问说明符的目的是控制抱愧派生类的派生类在内的派生类用户对于基类成员的访问权限:
派生类向基类的转换是否可访问由使用该转换的代码决定,同时派生类的派生访问说明符也会有影响:
我们经常在代码中看到using Base::size
这样的语句,很蒙圈不知道是干什么。这里是为了改变派生类继承的某个名字的访问级别。比如我们大部分内容想要私有继承,那么派生类列表访问类型使用私有就行。但是如果私有继承时某个或者某几个字段想要公开就可以使用 using 语句。举个例子:
class Base{
public:
int size() const{
return n;
}
protected:
int n;
};
class Sub:private Base{
public:
//保持size函数的可访问性
using Base::size;
protected:
using Base::n;
}
有时候我们很困惑 strcut 和 class 关键字的区别,其实它们唯一的区别就是具有不同的默认访问说明符和默认派生运算符。但是我们规范书写代码的话都尽量不适用默认访问权限,所以很多时候 struct 和 class 区别不大。
文本介绍了 Java 和 C++访问控制权限的区别,以及 C++派生访问说明符、派生类向基类转换的可访问性、改变个别成员的可访问性、默认的继承保护级别的内容。
领取专属 10元无门槛券
私享最新 技术干货