1. 私有和保护
成员函数或成员数据可以是公有或者私有的。如果是公有的,那么它们可以被直接访问;如果是私有的,那么它们无法被直接访问。同时,还有一个 protected
保留字,在没有使用继承的时候,它与 private
的效果是一样的,即无法被直接访问。如果使用了继承,我们就能体会到 protected
和 private
的差别。
private
(私有)和 protected
(保护)都能实现类的封装性。
private
能够对外部和子类保密,即除了成员所在的类本身可以访问之外,别的都不能直接访问;protected
能够对外部保密,但允许子类直接访问这些成员;
public
、private
和 protected
对成员数据或成员函数的保护程度可以用下表来描述:
在使用继承之前,我们必须保证父类是已经定义好的。如果父类是虚无的、没有被定义的,那么子类也就没什么好继承的了。定义一个子类的语法格式为:
class 子类名:继承方式 父类名;
2. 继承方式
public
是公有继承,或称为类型继承。它主要体现的是概念的延伸和扩展,父类所有的公有、保护成员都将按部就班地继承到子类中。父类的公有成员在子类中依然是公有的,父类的保护成员在子类中依然是保护的。
private
是私有继承,或称为私有的实现继承。它主要体现的是父类成员的重用。父类所有的公有、保护成员继承到子类时,类型会发生改变。父类的公有成员在子类中变成了私有成员,父类的保护成员在子类中也变成了私有成员。这时,我们可以利用从父类继承而来的成员函数来实现子类的成员函数,并且不必担心外部直接访问父类的成员函数,破坏了子类的秩序。
protected
是保护继承,或称为保护的实现继承。与私有继承类似,它也是体现父类成员的重用。只不过父类的公有成员和保护成员在子类中都变成了保护成员。因此,如果有一个孙类继承了子类,那么父类中的成员也将被继承,成为孙类的保护成员。
public
、private
和 protected
三种继承方式可以用下表描述。其中右下角的九个单元格表示各种父类成员在对应的继承方式下,成为子类成员后的性质。
3. 子类对象的构造
我们了解到当一个对象的成员数据是另一个对象的时候,就先运行成员对象的构造函数,再运行父对象的构造函数。但是继承的出现,会引入子类的构造函数。这时候,这些构造函数的运行顺序又是怎样的呢?
根据程序的运行结果,我们可以确定,父类的成员对象仍然是最先构造的,接着是运行父类的构造函数,最后运行子类的构造函数。也就是说子类对象是在父类对象的基础上扩展而成的。
另外,如果我们希望把子类的构造函数的参数传递给父类的构造函数时,可以在子类的构造函数定义中用以下格式调用父类的构造函数:
子类名::构造函数名(参数表):父类名(参数表)
猜想父类、父类成员对象、子类和子类成员对象的构造函数运行顺序,并设法验证。
结论:顺序依次为父类成员对象、父类、子类成员对象、子类。各成员对象的构造顺序参照它们在类中声明的顺序。
4. 子类对象的析构
我们就说它的运行顺序往往是和构造函数的运行顺序相反的。那么使用了继承之后,是否依然是这样的规律呢?
使用了继承之后,析构函数的运行顺序依然恰好与构造函数的运行顺序相反。