虚函数

虚函数的引入

1、【基类的对象指针】可以指向它的公有派生的对象,但是当其【指向公有派生类对象】时,它【只能访问派生类中从基类继承来的成员】,而【不能访问公有派生类中定义的成员】//很重要的总结!!!!!

注:对象指针——指针指向类的对象

例如:

base mb(50,50), *mp;//mp指向类base

dirive mc(10,20,30);

mp=&mb; mp->show(); //指针指向类base的对象mb

mp=&mc; mp->show();//指针指向类dirive的对象mc

不管指向基类对象的指针mp当前指向哪个对象(基类对象或派生类对象),mp->show()调用的都是基类中定义的show()。


3、虚函数就是在【基类中】被关键字virtual说明,并在【派生类中】重新定义的函数。

      虚函数定义后,就可以通过基类指针访问基类和派生类中的虚函数。//很重要的总结!!!!!

4、为什么?

关键字virtual指示C++编译器,使用语句“mp->show()”调用虚函数时,采用动态联编的方式,即在运行时确定调用哪个show()函数。调用同一类族中不同类的虚函数称为动态的多态性,即运行时的多态性


虚函数的定义

virtual 函数类型 函数名(形参表){     

            函数体   }

在虚函数重新定义时候,其函数原型包括函数类型函数名参数个数参数类型的顺序,都必须与基类中的原型完全相同。只是加了一个virtual而已

注意:

 (1)若在基类中,只声明虚函数原型(需加上virtual ),而在类外定义虚函数时,则不必再加virtual。

(2) 如果在派生类中没有对基类的虚函数重新定义,则公有派生类继承其直接基类的虚函数。一个虚函数无论被公有继承多少次,它仍然保持其虚函数的特性。

(3) 为了使程序更加清晰,最好在每一层派生类中定义该函数时都加上关键字virtual。

(4) 虚函数必须是其所在类的成员函数,而【不能是友元函数】,也不能是静态成员函数,因为虚函数调用要靠特定的对象来决定该激活哪个函数。

(5) 虽然使用对象名和点运算符的方式也可以调用虚函数,但是这种调用是在编译时进行的,是静态联编,它没有利用虚函数的特性。

【只有通过基类指针访问虚函数时才能获得运行时的多态性】。//重要!!!


虚析构函数

作用: 程序执行了动态联编,实现了运行的多态性。

3.虚函数与重载函数的关系【重点】

(1) 在一个派生类中重新定义虚函数是函数重载的另一种形式,但它不同于一般的函数重载。

(2) 【当普通的函数重载时,其函数的参数个数或参数类型必须有所不同,函数的返回类型也可以不同】。但是,【当重载一个虚函数时,要求函数名、返回类型、参数个数、参数的类型和顺序与基类中的虚函数原型完全相同】

(3) 当重载一个虚函数时, 如果仅仅返回类型不同,其余均相同,系统会给出错误信息;

(4) 若仅仅函数名相同,而参数的个数、类型或顺序不同,系统将它作为普通的函数重载,这时将失去虚函数的特性。


说明:

(1) 虚析构函数没有类型,也没有参数。

(2) 如果将基类的析构函数定义为虚函数,由该基类所派生的所有派生类的析构函数也都自动成为虚函数。

(3)不能声明虚构造函数,但是可以声明虚析构函数。


纯虚函数和抽象类

纯虚函数是在声明虚函数时被“初始化”为0的虚函数。

virtual void area( )=0;

作用:其实基类函数并不需要这个函数,是在基类中为其派生类保留一个函数的名字,以便派生类根据需要对它进行重新定义。

纯虚函数的特点

① 纯虚函数没有函数体

② 最后面的“=0”并不表示函数的返回值为0,它只起形式上的作用,告诉编译系统“这是纯虚函数”;

 ③ 纯虚函数不具备函数的功能,不能被调用


如果一个类至少有一个纯虚函数,那么就称该类为抽象类【重点】

作用是作为一个类族的共同基类,相关的派生类是从这个基类派生出来的。

几点规定:

(1) 由于抽象类中至少包含有一个没有定义功能的纯虚函数,因此抽象类只能用作其他类的基类,不能建立抽象类对象。 

(2) 在派生类中,如果对基类的纯虚函数没有重新定义,则该函数在派生类中仍是纯虚函数,该派生类仍为抽象类。

(3) 抽象类不能用作参数类型、函数返回类型或显式转换的类型。但可以声明指向抽象类的指针变量,此指针可以指向它的派生类,进而实现多态性。

你可能感兴趣的:(虚函数)