C/C++多态性(polymorphism)虚函数

多态性(polymorphism),

         从系统实现的角度,多态性分为两类:静态多态性和动态多态性。函数重载和运算符重载实现的多态性属于静态多态性,在程序编译时系统就能决定调用的是哪个函数,因此有称为编译时的多态。静态多态性是通过函数的重载实现的(运算符重载实质上也是函数的重载)。动态多态性是在程序运行过程中才动态地确定操作所针对的对象。它又称为运行时的多态性。动态多态性是通过虚函数(virtual function)实现的。

静态多态:函数的重载和运算符的重载

动态多态:虚函数

在什么情况下应当声明虚函数

使用虚函数时,有两点注意的:

  1. 只能用virtual声明类的成员函数,使它成为虚函数,而不是能将类外的普通函数声明为虚函数。因为虚函数的作用是允许在派生类中对基类的虚函数中心定义。显然,它只能用于类的层次结构中。
  2. 一个成员函数被声明为虚函数后,在同一个类族中的类就不能再定义一个非virtual的但与该虚函数具有相同的参数(包括个数和类型)和函数返回值类型的同名函数。
根据什么考虑是否把一个成员函数声明为虚函数呢?主要是以下几点:

  1. 首先看成员函数所在的类是否会作为基类。然后看成员函数在类的继承后有无可能更改功能,如果希望其功能的,一般应该将它声明为虚函数。
  2. 如果成员函数在类被继承后功能不需要修改或者派生类用不到该函数,则不要把它声明为虚函数。不要仅考虑到要做为基类而把类中的所有成员函数都声明为虚函数。
  3. 应该考虑对成员函数的调用是通过对象名还是通过基类指针或引用去访问,如果是基类指针或引用去访问的,则应当声明为虚函数。
  4. 有时,在定义虚函数时,并不定义其函数体,即函数体为空的。它的作用只是定义一个虚函数名,具体功能留给派生类去添加。

        需要说明的是:使用虚函数,系统要有一定的空间开销。当一个类带有虚函数时,编译系统会为该类构造一个虚函数表(virtual function table,vtable),它是一个指针数组,存放每一个虚函数的入口地址。系统在进行动态关联时的时间开销是很少的,因此,多态性是高效的。

虚析构函数

       情况:析构函数的作用是在对象撤销之前做必要的“清理现场”的工作。当派生类的对象从内存中撤销时一般先调用派生类的析构函数,然后再调用基类的构造函数。但是,如果用new运算符建立了临时对象,若基类中有析构函数,并且定义了一个指向该基类的指针变量。在程序用带指针参数的delete运算符撤销对象时,会发生一种情况:系统会只执行基类的析构函数,而不执行派生类的析构函数。

        人们的愿望是先调用派生类的析构函数,然后再调用基类的构造函数。当基类的析构函数为虚函数时,无论指针指的是同一类族中的哪一个对象,当对象撤销时,系统会采用动态关联,调用相应的析构函数,对该对象进行清理工作。如果将基类的析构函数声明为虚函数,又该基类所派生的所有派生类的析构函数也都自动成为虚函数(即使派生类的析构函数与基类的析构函数名字不同)。

        在程序中最好把积累的析构函数声明为虚函数。这将使所有的派生类自动成为虚函数。这样,如果程序中用的delete运算符准备删除一个对象,则delete运算符的操作对象是指向派生类对象的基类指针,则系统会调用相应类的析构函数。

       构造函数不能声明为虚函数。这是因为在执行构造函数时类对象还未完成建立过程,当然谈不上函数与类对象的关联。

纯虚函数和抽象类

      概念: 纯虚函数实在声明虚函数时被“初始化”为0的函数。一般形式为:

     virtual 函数类型 函数名 (参数表列)=0;

    

virtual float area()const = 0;
注意:

  1. 纯虚函数没有函数体;
  2. 最后面的“=0”并不是返回值为0,它是其形式上的作用,告诉编译系统“这是纯虚函数”;
  3. 这是一个声明语句,最后应有分号。
    纯虚函数只有函数的名字而不具备函数的功能,不能被调用。可以说它是”徒有其表,而无其实“。它只是通知编译系统:”在这里声明了一个虚函数,留待派生类中定义“。在派生类中对此函数提供定以后,它才具备函数的功能,可以被调用。

   纯虚函数的作用是在基类中为其派生类保留一个函数名,以便派生类根据需要对它进行定义。如果再在基类中没有保留的函数名字,则无法实现多态性。如果在一个类中声明了一个纯虚函数,而在其派生类中没有对该函数定义,则该虚函数在派生类中仍然是纯虚函数。

抽象类

     一个优秀的软件工作者在开发一个大的软件时,绝不会从头到尾都有自己编写代码,他会充分利用已有资源(例如类库)作为自己工作的基础。这种不用来定义对象而只作为一种基本类型用作继承的类,称为抽象类(abstract class),由于它常用作基类,通常称为抽象基类(abstract base class)凡是包含纯虚函数的类都是抽象类。因为纯虚函数是不能被调用的,包含纯虚函数的类是无法建立对象的。抽象类的作用是作为一个类族的共同基类,或者说,为一个类族提供一个公共的接口。


你可能感兴趣的:(多态,编译)