类的三方法:封装,继承,多态。
封装:使用一整套方法去创建一个新的类型,这叫类的封装。
继承:从一个现有的类型基础上,稍作改动,得到一个新的类型的方法,叫类的继承。
多态:当有几个不同的子类对象时,对象调用的函数会依据对象类型来调用相应类型的成员函数。
继承
1. 继承的主要目的是为了代码复用。
创建子类对象时,先创建父类,再创建子类。
析构时,先析构子类,再析构父类。
2. 访问权限:public, protected, private.
protected表示这种成员可以被子类继承和访问,但是外界却像private一样不可访问。
父类的private成员并不是不继承,而是对子类扩展的成员函数不可见。
public派生规则:
父类成员访问权限 子类继承自父类成员的访问限定
publicpublic
protectedprotected
private不可见
protected派生规则:
父类成员访问权限 子类继承自父类成员的访问限定
publicprotected
protectedprotected
private不可见
private派生规则:
父类成员访问权限 子类继承自父类成员的访问限定
publicprivate
protectedprivate
private不可见
3. 类型转换
父类A子类B
A *p = new B; 可以
B *p = new A; 不可以
p调用的成员方法为父类(A)的方法,非子类B的成员方法。属编译时绑定(因p的指针类型为A *),如要访问子类,需要使用多态(父类相应方法定义为virtual)。
A a;
B *p;
p = &a; 可以
p访问成员变量时可能越界(因p的成员变量多余a)
多态
声明为vitual的成员函数称为虚函数。
有虚函数的类都有一个隐含的指针成员vptr,指向一个虚函数表。(一个类一个)
每个父类或子类都各自有一张虚函数表。在构造对象时,对象的vptr成员指向该类的虚函数表。
包含虚函数的类的sizeof应多加4个字节,用于存放vptr(虚函数表指针)。
一旦某个函数在父类中声明为virtual,在所有继承它的子类中这个函数也是virtual的,子类可以不必写virtual关键字。
声明为virtual的函数,在运行时确定执行体,属动态绑定,dynamic binding。调用子类的具体实现。如果一个成员函数声明为virtual并在末尾加上=0而没有提供函数的实现,称为虚函数,拥有虚函数的类称为抽象类,抽象类不能实例化(或者说不能创建该类的对象),而只能被其他类继承。
抽象类也称为接口,继承了某个抽象类也称实现了某个接口。