(一)虚函数
定义:虚函数,是指被virtual关键字修饰的成员函数。
在某基类中声明为 virtual 并在一个或多个派生类中被重新定义的成员函数,
用法格式为virtual 函数返回类型 函数名(参数表) {函数体};实现多态性,通过指向派生类的基类指针或引用,访问派生类中同名覆盖成员函数。
要点:
-
虚函数对类的内存影响:需要增加一个指针类型大小的内存
-
不管多少个虚函数,只会增加一个指针类型大小的内存
-
虚函数表的概念: 指向虚函数的指针
-
习惯上虚函数一般不声明为内联函数,因为对虚函数的调用需要动态绑定,而对内联画数的处理是静态的,所以虚函数一般不能以内联函数处理。但将虚函数声明为内联函数也不会引起错误。
在UML中,一般的虚函数是通过在成员函数前添加<<virtual>>构造型来表示。 -
具体代码:
#include <iostream> #include <string> using namespace std; class CC { public: virtual void print() { cout << "我是一个虚函数" << endl; } virtual void printData() { cout << "我是第二个虚函数" << endl; } protected: }; //公有继承 class Boy :public CC { public: //父类是虚函数,子类也是虚函数 void print() { } protected: }; int main() { CC cc; Boy bb; cout << "CC:" << sizeof(CC) << endl; cout << "Boy:" << sizeof(Boy) << endl;//无论多少虚函数,只会增加一个指针类型的内存大小 return 0; }
(二)纯虚函数
定义:纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。
纯虚函数也可以叫抽象函数,一般来说它只有函数名、参数和返回值类型,不需要函数体。这意味着它没有函数的实现,需要让派生类去实现。
C++中的纯虚函数,一般在函数签名后使用=0作为此类函数的标志。Java、C#等语言中,则直接使用abstract作为关键字修饰这个函数签名,表示这是抽象函数(纯虚函数)。
简言之,
纯虚函数也是虚函数一种,只是没有函数体
-
纯虚函数声明格式:virtual 函数类型 函数名(参数列表);
-
纯虚函数不同于函数体为空的虚函数:纯虚函数根本就没有函数体,而空的虚函数的函数体为空;前者所在的类是抽象类,不能直接进行实例化,而后者所在的类是可以实例化的。它们共同的特点是都可以派生出新的类,然后在新类中给出虚函数新的实现,而且这种新的实现可以具有多态特征。
-
具体代码:
#include <iostream> using namespace std; class CC { public: virtual void print() = 0; protected: }; int main() { //CC c;错误写法:抽象类不能构造对象 CC* p = NULL; return 0; }
-
具有一个或者多个纯虚函数的类叫做抽象类
-
抽象类不能实例化,即不能定义一个抽象类的对象
-
但是可以定义一个抽象类的指针和引用。
-
通过指针或引用,可以指向并访问派生类对象,进而访问派生类的成员。该访问具有多态特征。
-
(三)虚析构函数
定义:虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。
声明语法:virtual ~类名();
如果一个类的析构函数是虚函数,那么,由它派生而来的所有子类的析构函数也是虚函数。析构函数设置为虚函数之后,在使用指针引用时可以动态绑定,实现运行时的多态,保证使用基类类型的指针就能够调用适当的析构函数针对不同的对象进行清理工作。简单来说,如果有可能通过基类指针调用适当的析构函数针对不同的对象进行清理工作。简单来说,如果有可能通过基类指针调用对象的析构函数(delete),就需要让基类的析构函数成为虚函数,否则会产生不确定的后果。
(四)多态
多态指的是因为指针的不同对象的赋值操作所导致的统一行为的不同结果。多态的这个概念的东西不太重要,重要的是什么样情况调用什么样的行为。
-
正常指针和正常对象调用行为,就近原则
-
父类指针被子类对象初始化
-
函数有virtual 看对象类型
-
函数没有virtual 看指针类型
-
-
final关键字 禁止子类重写父类方法
-
override 显示说明当前函数重写函数