1. 虚函数
语法规范:
在类成员方法的声明(不是定义)语句前面加个单词:virtual
注意:
(1)子类可以重新定义基类的虚函数,我们把这个行为称之为复写(override)
(2)子类可自主选择是否要提供一份属于自己的个性化虚函数实现。
2. 纯虚函数
语法规范:
在虚函数的声明语句末尾中加个 =0
virtual 函数类型 函数名 (参数表列) = 0;
class Person //基类
{
virtual void Display () = 0; // 纯虚函数 声明
protected :
string _name ; // 姓名
};
class Student : public Person //子类
{
//纯虚函数 定义
};
注意:
(1)纯虚函数没有函数体,只有函数的名字而不具备函数的功能,不能被调用;
(2)最后面的“=0”并不表示函数返回值为0,它只起形式上的作用,告诉编译系统“这是虚函数”;
(3)这是一个声明语句,最后有分号;
(4)子类必须提供一份属于自己的个性化纯虚函数实现。
(5)纯虚函数的作用是在基类中为其派生类保留一个函数的名字,以便派生类根据需要对他进行定义。如果在基类中没有保留函数名字,则无法实现多态性。
如果在一个类中声明了纯虚函数,在其派生类中没有对其函数进行定义,则该虚函数在派生类中仍然为纯虚函数。
3.抽象类
定义:不用定义对象而只作为一种基本类型用作继承的类叫做抽象类(也叫接口类),凡是包含纯虚函数的类都是抽象类。
注意:抽象类不能使用new出对象,只有实现了这个纯虚函数的子类才能new出对象。
即,抽象类不能实例化出对象。纯虚函数在派生类中重新定义以后,派生类才能实例化出对象。
主要作用:抽象类的作用是作为一个类族的共同基类,为一个类族提供公共接口。即将有关的操作作为结果接口组织在一个继承层次结构中。抽象类为派生类提供一个
公共的根,派生类将具体实现在基类中作为接口的操作。
4. 虚函数和纯虚函数的区别
a. 定义一个函数为虚函数,不代表函数为不被实现的函数;
b. 定义一个函数为虚函数,是为了允许用基类的指针来调用子类的这个函数;
c. 虚函数只能借助于指针或引用来达到多态的效果;
d. 定义一个函数为纯虚函数,才代表函数没有被实现;
e. 定义纯虚函数是为了实现一个接口,起到规范的作用,规范继承这个类的程序员必须实现这个函数;
5.总结
1、派生类重写基类的虚函数实现多态,要求函数名、参数列表、返回值完全相同。(协变除外)
2、基类中定义了虚函数,在派生类中该函数始终保持虚函数的特性。
3、只有类的非静态成员函数才能定义为虚函数,静态成员函数不能定义为虚函数。
4、如果在类外定义虚函数,只能在声明函数时加virtual关键字,定义时不用加。
5、构造函数不能定义为虚函数,虽然可以将operator=定义为虚函数,但最好不要这么做,使用时容易混淆
6、不要在构造函数和析构函数中调用虚函数,在构造函数和析构函数中,对象是不完整的,可能会出现未定义的行为。
7、最好将基类的析构函数声明为虚函数。(析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但是构成覆盖,这里编译器做了特殊处理)
8、虚表是所有类对象实例共用的虚表剖析。
6.结论:
(1)一个基类如果包含一个或一个以上纯虚函数,就是抽象基类。抽象基类不能也没必要定义对象。
(2)在类的层次结构中,顶层或最上面几层可以是抽象基类。抽象基类体现了本类族中各类的共性,把各类中共有的成员函数集中在抽象基类中声明。
(3)抽象基类是本类族的共公共接口,即就是从同一基类中派生出的多个类有同一接口。
7.推迟联编(动态联编)
一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。
浙公网安备 33010602011771号