一、 访问权限
C++通过 public
、protected
、private
三个关键字来控制成员变量和成员函数的访问权限,它们分别表示公有的
、受保护的
、私有的
,被称为成员访问限定符。
在类的内部(定义类的代码内部),⽆论成员被声明为 public
、protected
还是 private
,都是可以互相访问的,没有访问权限的限制。
在类的外部(定义类的代码之外),只能通过对象访问成员,并且通过对象只能访问 public
属性的成员,不能访问private
、protected
属性的成员。
对于公有(public
)继承,派生类中所有成员的访问限定符不变;对于保护(protected
)继承,派生类中所有public
成员访问限定符变为protected
;对于私有(private
)继承,派生类中所有成员访问限定符变为private
。可以理解为只降不升。
因此,⽆论共有继承、私有和保护继承,私有成员不能被“派⽣类”访问,因为私有成员始终是私有成员,只能在定义该成员的类(基类)内部访问;而基类中的共有和保护成员能被“派⽣类”访问。对于派生类的派生类,公有或保护继承时,其可以访问基类全部public
和protected
成员;私有继承时,则无法访问任何基类成员。这种访问称为垂直访问。
对于共有继承,只有基类中的共有成员能被“派⽣类对象”访问,保护和私有成员不能被“派⽣类对象”访问。对于私有和保护继承,基类中的所有成员不能被“派⽣类对象”访问。这种访问称为水平访问。
需要注意的是,访问权限符作用于编译期(很重要,下面要用到!),主要是让编译器来判断成员的访问是否合法,一旦程序进入运行期,它们也就没有意义了。
二、 重载和重写
- override是重写(覆盖)了⼀个⽅法,以实现不同的功能,⼀般是⽤于⼦类在继承⽗类时,重写⽗类⽅法。C++11新增关键字override可以用于在编译器检查重写是否正确,前提是重写的函数必须在基类中有定义,并且是虚函数。
规则:
- 重写方法的参数列表,返回值,所抛出的异常与被重写方法⼀致。
- 被重写的方法不能为private。解释一下:并不是说基类private方法不能被重写,不管基类方法是什么访问权限符,派生类是否能够访问,派生类都是可以重写的,但是问题在于重写一般都是用于运行时多态,运行时多态的前提是通过编译,一旦基类某个虚函数为
private
,而我们使用指向派生类对象的基类指针去访问该方法(派生类已经重写),编译是不通过的!因为基类指针在编译器是无权访问该方法的(此时编译器用的是基类版本),这样也就无法实现运行时多态了,对于protected方法也是同理。所以,上面说的访问权限符作用于编译期是很重要的 - 静态方法不能被重写为非静态的⽅法。解释一下:实际上从多态和虚函数的角度出发,静态方法不可以被重写,因为它不存在于对象中,也就无法成为虚函数,自然不能被重写。在基类和派生类中定义的具有相同函数签名的静态成员函数实际上是两个函数。另外还有一点要注意的是,同一个类中,不可以同时定义函数签名相同(方法名和参数形式都相同)的静态方法和非静态方法,过不了编译。
- 重写方法的访问修饰符⼀定要⼤于被重写⽅法的访问修饰符(public>protected>default>private)。这个好理解,继承是降,重写就是升。
- overload是重载,这些⽅法的名称相同⽽参数形式不同。⼀个方法有不同的版本,存在于⼀个类中。重载必须是同一个作用域下的!比如类内函数和全局函数不可以重载。重载的本质是函数名相同但函数签名不同的函数,不会覆盖基类函数,但是函数签名完全相同的派生类中的方法会覆盖基类的方法。
规则:
- 不能通过访问权限、返回类型、抛出的异常进⾏重载
- 不同的参数类型可以是不同的参数类型,不同的参数个数,不同的参数顺序(参数类型必须不⼀样)
- 方法的异常类型和数目不会对重载造成影响
PS: 除非使用虚函数或者是重载匹配到基类中的函数,否则使用什么类的指针,调用的就是那个类里的方法。如果基类和派生类有函数签名相同的方法,那么在使用子类对象/指针访问时,基类方法被覆盖,优先调用派生类的方法,如要用子类对象/指针去访问基类的该方法,可以使用作用域限定符号。