type
status
date
slug
summary
tags
category
icon
password
Property
正如每个控制其自动成员的初始化,每个类也会控制其成员是否对派生类可见。
protected 成员
类使用
protected
修饰那些对派生类可见,但是不想被其他公共访问使用的成员。protected
可以认为是private
和public
的中和:- 与
private
成员类似,protected
成员对类的用户是不可见的
- 与
public
成员类似,protected
成员对派生类的成员和友元是可见的
还有一条很重要的关于
protected
特性是:派生类的成员和友元只能通过派生对象访问基类的protected
成员。派生类不能访问独立的基类对象的protected
成员。第二个函数不是
Base
的友元,因而,它不能访问 Base 对象的受保护成员。为了防止第二种用法,派生类的成员或友元只能访问嵌套在派生对象中的基类子对象中的受保护成员。对于独立的基类对象并不具有特殊的访问权限。public, private 和 protected 继承
访问一个类继承来的成员是由基类中的访问说明符和派生列表中的访问说明符共同决定的。
- 基类
private
成员在派生类中无论以说明方式继承都是不可见的。这里的不可见是指基类的私有成员被继承到了派生类对象中,但是语法限制上派生类对象不管再类里面还是在类外面都不能去访问它。
- 基类
private
成员在派生类中是不能被访问的,如果基类成员不想再类外直接被访问,但需要在派生类可以访问,就定义为protected。因此可以看出protected保护成员限定符是因为继承才出现的。
- 基类的私有成员在子类都是不可见的。基类的其他成员在子类的访问方式==(成员在基类的访问限定符和继承方式中的)小的那个,
public > protected > private
。
- 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过最好显示的写出继承方式
- 在实际运用中一般使用的都是public继承,几乎很少使用protected和privated继承,也不提倡使用protected和private继承,因为protected和private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。
派生访问说明符并不影响派生类的成员和友元对其直接基类的成员访问权限。访问直接基类的成员是由基类自身的访问说明符决定的。
public
继承和 private
继承的派生类都可以访问基类的 protected
成员,而都不能访问基类的 private
成员。派生访问说明符的作用在于控制派生类的用户对从基类继承来的成员的访问权限,这些用户包括从这个派生继承的其它派生类:
Pub_Derv
和Priv_Derv
都从基类中继承pub_mem
函数。当继承是public
的,成员将保持其可见性,所以d1
可以调用pub_mem
。而 Priv_Derv
中基类的成员是private
的,此类的用户不能调用pub_mem
。派生类的派生访问说明符还会控制从此派生类进行继承的类对其基类的访问权限:
对于
Priv_Derv
的派生类来说,Priv_Derv
从基类中继承来的所有成员都是私有的。如果使用
protected
继承,Base
中的public
成员在派生类中将变成protected
的,其用户将不能访问继承来的成员,但是其子类可以访问这些成员。派生类到基类的转换的可见性
派生类到基类的转换是否可见取决于哪些代码尝试使用这些转换以及派生列表的访问说明符。假设 D 继承自 B:
- 仅当 D 是公有继承 B 时,用户代码可以使用派生类到基类的转换,若以 protected 或 private 继承则不可以;
- D 的成员函数或友元可以使用派生类到基类的转换,而忽略 D 是如何继承 B 的,派生类到直接基类的转换对于派生类的成员和友元来说总是可访问的;
- D 的派生类的成员或友元,当 D 是 public 或 protected 继承 B 时,可以使用派生类到基类的转换。如果 D 是私有继承 B 则这种转换不可使用;
在给定代码的任何位置,如果基类的 public 成员是可见的,那么派生类到此基类的转换就是可见的。
类设计和 protecte 成员
在没有继承时,类只有两种用户:普通用户和实现者。普通用户书写使用类对象的代码;这种代码只能访问类的 public 成员(接口)。实现者书写类的成员和友元中的代码,类的成员和友元可以访问类的 public 和 private 部分(实现)。
在继承的情况下,有第三种用户:派生类。基类使得派生类可访问的实现部分为 protected 。protected 成员对于普通用户来说不可见,private 成员对于派生类和派生类的友元来说不可见。
与别的类一样,基类使其接口成员为 public 的。作为基类的类会将其实现分为可被派生类访问和保留给基类自身和其友元访问的部分。如果提供给派生类用于其实现的操作或数据应该设为 protected 的,否则,实现成员应该设为 private 的。
友元关系和继承
正如友元不具有传递性质(一个类是另一个类的友元并不意味着这个类自己的友元可以访问那个类),友元关系不会被继承。基类的友元对于派生类成员没有特殊的访问权限,派生类的友元对于基类成员没有特殊访问权限。如:
f3
是合法的确有点奇怪,但是这与每个类控制自己的成员的访问权限并不冲突。Pal
是Base
的友元,所以Pal
可以访问Base
对象的私有成员,这种访问权限即便是当基类对象是其派生类对象的一部分时依然成立。如果一个类是另一个类的友元,那么仅仅是那个类的友元,那个类的基类或派生类都不是这个类的友元:
友元关系不能继承,每个类控制自己的成员的访问级别。
改变单个成员的访问权限
有时需要改变特定的派生类继承来的名字的访问级别。可以通过使用
using
声明来指定:这里值得注意的是派生类不能改变基类的私有成员的访问级别,原因在于它们对派生类根本不可见。
由于
Derived
使用了private
继承,所以,size
和n
默认是Derived
的私有成员。using
声明调整了这些成员的可见性。Derived
的用户代码可以访问其 size 成员,Derived 的派生类可以访问 n 成员。类内的 using 声明可以将其直接或间接基类的可访问名字指定为任何访问级别。如果using
出现在private
部分,则只能被类的成员或友元访问。如果出现在public
部分,则可以被所有用户代码访问。如果出现在protected
部分,则名字可以被成员、友元和派生类访问。派生类只能给它可以访问的基类名字使用
using
声明。默认继承的派生访问说明符
C++
中可以使用 struct
和 class
关键字定义类,并且具有不同的默认访问说明符。类似的,默认派生说明符依赖于使用哪个关键字定义派生类。用class
定义的派生类默认是private
继承;用sturct
定义的派生类默认是public
继承:任何用关键字
struct
或class
定义的类之间有什么更深层次的不同是一个普遍的错误。它们之间唯一的区别就是成员的默认访问说明符和默认的派生访问说明符之间的不同。除此之外更无别的区别了。私有派生的类应该显式给出
private
而不是依赖于默认访问说明符。通过显式指出让其它程序员可以知道私有继承是有意为之,而不是由于错误导致的。