# 使用方法
* 在基类用virtual声明成员函数为虚函数。这样就可以在派生类中重新定义此函数,为它赋予新的功能,并能方便地被调用。在类外定义虚函数时,不必再加virtual。
* 在派生类中重新定义此函数,要求函数名、函数类型、函数参数个数和类型全部与基类的虚函数相同,并根据派生类的需要重新定义函数体。
* 当一个成员函数被声明为虚函数后,其派生类中的同名函数都自动成为虚函数,派生类重新声明该虚函数时,可以加virtual,也可以不加。
* 派生类中没有对基类的虚函数重新定义,则派生类简单地继承其直接基类的虚函数。
* 定义一个指向基类对象的指针变量,并使它指向同一类族中需要调用该函数的对象。通过该指针变量调用此虚函数,此时调用的就是指针变量指向的对象的同名函数。
# 声明格式
~~~
virtual 返回类型 函数名(形参列表);
~~~
# 作用
* 允许在派生类中重新定义与基类同名的函数,并且可以通过**基类指针**或**引用**来访问基类和派生类中的同名函数。
* 同一类族中不同类的对象,对同一函数调用作出不同的响应。
# 虚函数与重载的区别
* 涵数重载处理的是同一层次上的同名函数问题,是横向重载
* 虚函数处理的是不同派生层次上的同名函数问题,是纵向重载
* 同一类族的虚函数的首部是相同的,而函数重载时函数的首部是不同的(参数个数或类型不同)。
# 注意
* 只能用virtual声明类的成员函数,使它成为虚函数,而不能将类外的普通函数声明为虚函数。
* 一个成员函数被声明为虚函数后,在同一类族中的类就不能再定义一个非virtual的但与该虚函数具有相同的参数(包括个数和类型)和函数返回值类型的同名函数。
* 如果该类会成为基类,且有成员函数在被继承后,需要修改功能
* 如果是通过基类指针或引用去访问的,则应当声明为虚函数
# 虚表指针
* 当一个类带有虚函数时,编译系统会为该类构造一个虚函数表,它是一个指针数组,存放每个虚函数的入口地址。
* 而每当用多态类创建一个对象时,编译器就会自动生成一个虚表指针
* 由构造函数正确对其初始化,使其指向该对象所属类的虚函数表,最后将它放置在该多态类对象结构的开头。
* C++采用的是绝对地址+偏移量的方法访问虚函数的,这样,在调用虚函数时,采用**滞后联编**,就能够映射到正确的虚函数了
* 如果将基类的析构函数声明为虚函数时,由该基类所派生的所有派生类的析构函数也都自动成为虚函数
* 最好把基类的析构函数声明为虚函数
* **构造函数不能声明为虚函数**
- 介绍
- 编程设计语言
- 第一章 对C++的初步认识
- 1.2 最简单的C++程序
- 1.3 C++对C的补充
- 1.3.1 return
- 1.3.2 输入输出流
- 1.3.3 putchar 和 getchar
- 1.3.4 用const定义常变量
- 1.3.5 函数原型声明
- 1.3.6 内置函数
- 1.3.7 函数重载
- 1.3.8 函数模板
- 1.3.9 有默认值的参数
- 1.3.10 作用域
- 1.3.11 const修饰指针
- 1.3.12 引用
- 1.3.13 生命期
- 1.3.14 变量
- 1.3.15 字符串变量
- 第二章 类与对象
- 2.2 类的声明和对象的定义
- 2.3 类的成员函数
- 第三章 关于类和对象的进一步讨论
- 3.1 构造函数
- 3.1.1 对象的初始化
- 3.1.2 构造函数
- 3.2 析构函数
- 3.3调用析构函数和构造函数的顺序
- 3.4 对象数组
- 3.5 对象指针
- 3.6 共享数据的保护
- 3.7 对象的建立与释放
- 3.8 对象的赋值与复制
- 3.9 静态成员
- 3.10 友元
- 3.11 类模板
- 第四章 运算符重载
- 数据类型转换
- 运算符重载
- 重载流插入运算符和流提取运算符
- 第五章 继承与派生
- 继承与派生
- 第六章 多态性与虚函数
- 多态性
- 虚函数
- 纯虚函数与抽象类