C++它指定虚函数的行为,但实现的作者编译器.

通常,编译器处理虚函数的方法是给每个对象加入一个隐藏成员.隐藏成员中保存了一个指向函数地址数组的指针.

这个数组称为虚函数表(virtual function table,vtbl).虚函数表中存储了为类对象进行声明的虚函数的地址.

比如:基类对象包括一个指针,该指针指向基类的虚函数表.

派生类对象包括一个指针,该指针指向一个独立的虚函数表.假设派生类提供了虚函数的新定义,虚函数表将保存新的函数地址.

假设派生类没有又一次定义虚函数,虚函数表将保存原版本号的地址.假设派生类定义了新的虚函数,则将该函数地址也加入到虚函数表中!

看以下的样例:

#include <iostream>
#include <string>
using namespace std;
class Animal{
protected:
string name;
public:
Animal(const string &s):name(s){
}
virtual ~Animal(){
}
//非虚函数
void eat()const{
cout<<"Animal eat!"<<endl;
}
//不被重写的虚函数
virtual void run()const{
cout<<"Animal run!"<<endl;
} //会被重写的虚函数
virtual void speak()const{
cout<<"I'm a Animal!"<<endl;
}
};
class Dog:public Animal{
public:
Dog(const string &s):Animal(s){
}
virtual ~Dog(){
}
//新定义的函数eat,将掩盖旧的版本号,非重写(重写是指重写virtual函数)
void eat()const{
cout<<"Dog eat!"<<endl;
}
//重写speak()
virtual void speak()const override{
cout<<"This's a Dog!"<<endl;
}
//新的虚函数
virtual void fun1()const{
}
};
int main(){
Animal a("AnimalOne");
Dog d1("DogOne"); Animal *p1=&a;
Animal *p2=&d1;
p1->speak();
p2->speak();
p1->eat();
p2->eat(); //call Animal::eat()
p1->run();
p2->run(); //call Animal::run() Animal &r1=a;
Animal &r2=d1;
r1.speak();
r2.speak();
r1.eat();
r2.eat();
r1.run();
r2.run(); return 0; }

注意eat不是虚函数,不会保存在虚函数表中

//Animal虚函数表
地址:1000

Animal::run()        4000

Animal::speak()                  5000

Dog虚函数表  地址:2000

Dog::run()        4000(没有被重写,保存原地址)

Dog::speak()  
7000(重写了,保存新地址)

Dog::fun() 8000(新的虚函数,保存地址)

具体分析以下的代码

p1->speak();
//找到Animal中speak的地址,5000

p2->speak();
//找到Dog中speak的地址,7000,运行代码Dog::speak();

p1->run();
//同上

p2->run();
//

这样,对于虚函数表就有了一的初步认识!


版权声明:本文博客原创文章。博客,未经同意,不得转载。

最新文章

  1. EF-CodeFirst-1 玩起来
  2. bitnami-redmine 安装与插件使用
  3. 无法解析的外部符号 __imp__InitCommonControlsEx@4
  4. C/C++代码中的笔误
  5. cocos2d-x类型转换(CCstring int string char UTF-8互转)
  6. 【BZOJ】【1042】【HAOI2008】硬币购物
  7. 使用VisualStudio进行单元测试之三
  8. 用CSS+Jquery实现一个漂浮的窗体
  9. jQuery $.fn.extend方式自定义插件
  10. C++使用简单的函数指针
  11. 【NOIP2015】反思+题解
  12. ios 初体验&lt;页面切换&gt;
  13. Redis安装及使用笔记
  14. CTF---Web入门第三题 这个看起来有点简单!
  15. 查看ntp时间是否同步
  16. PyQt5简介及demo
  17. 创建Java多线程的两种方式和线程异常
  18. day_6.26 反射
  19. Objective的头文件@interface属性
  20. physics---hdu5826(积分)

热门文章

  1. Linux与Windows 10用grub引导教程
  2. oracle 让人抓狂的错误之 null值 与 无值(无结果)-开发系列(一)
  3. 并发队列ConcurrentLinkedQueue 和 阻塞队列LinkedBlockingQueue用法
  4. ArcGIS二次开发入门(一)
  5. mysqldump备份脚本
  6. jQuery笔记-jQuery筛选器children()详解
  7. QT学习记录之环境搭建
  8. 如何使用Name对象,包括WorkspaceNames和DatasetNames
  9. erlang lists
  10. 【t014】拯数