虚函数
虚函数,知道怎么用,也知道虚函数表这么个东西的存在,但是一直不是很明白它到底是怎么样工作的,今晚一探究竟.
C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言之就是用父类的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.
也就是说,假如我有一个A类,里面写了个虚函数fun1,如果B类继承了A类,然后覆盖了fun1,我通过 A* a = new B();的方式就可以调到B里面的真正实现.如果是习惯了其他语言,比如java, 咋一看,这就是函数重载嘛,关虚函数啥事呢?但是,如果你在c++上,跟java一样的用法的话,是得不到想要的结果的,假如fun1你没有加上虚函数标识(virtual),然后B也写了个fun1函数,然后 B* b = new B(); b->fun1(); 调用的是B里面的fun1,而A* b = newB(); b->fun1(); 的话,调用的则是A里面的fun1了,如果A的fun1定义加上了virtual 则调到的就全是B的fun1了.
至于纯虚函数,那就是相当于接口了,没有实现而已.
这也就是我之前认识到的虚函数的用法了.
但是我并不明白,虚函数是怎么工作的,那个虚函数表,又是个什么东西.
经查,函数表就是记录了虚函数地址的一张表,它是通过替换函数地址来实现正确调用的,
比如我们有一个类
class A
{
public:
virtualint fun(){ return 1; }
virtualint fun1(){ return 2; }
virtualint fun2(){ return 2; }
};
class B:public A
{
public:
intfun(){ return 2; }
};
class C :public A
{
public:
intfun1(){ return 2; }
};
然后我们创建对象
A* a = new A();
A* b = new B();
A* c = new C();
通过打断点,就可以看到b和c 里面虚函数表的信息
其中,_vfptr,就是虚函数表的地址,后面跟的就是对于的函数地址
从这个图我们就可以看出,abc三个变量的虚函数表地址是不一样的,也就是说,子类继承了父类以后,就会自动给其创建个虚函数表,而且这个表的地址是唯一的,创建多个B的话,其虚函数表的地址都是一样的.
因为B覆盖了A类的fun,所以它的fun地址是跟A与C的fun地址是不一样的,同理C的fun1也一样,而fun2 B和C都没有覆盖,所以三者的地址是一样的.
我们也可以通过这个地址去直接访问函数,具体方式我是参考这里的,不赘述http://blog.youkuaiyun.com/haoel/article/details/1948051/
我现在在想,可不可以通过找寻这个地址的方式,实现一些回调函数,因为按照之前的理解的话,回调函数都是不能设置为类的成员函数的,
明天试一试,今晚太晚了来不及了.不过也算是能大概知道虚函数表是个什么样的东西,怎么去看了.