图解虚函数的实现

基类指针(或函数)调用派生类中与基类同名函数时,它只能看到基类的函数。

class A {

public:

virtual void fun0() { cout << "A::fun0" << endl; }

int a;

int b;

};

int main(int argc, char* argv[])

{

A a;

cout << "Size of A = " << sizeof(a) << endl;

return 0;

}

结果如下:Size of A = 12 其虚函数在内存中结构是这样的:

如果有两个虚函数时VPTR指针如下:

再看下面的程序:

class A {

public:

virtual void f() { }

};

class B {

public:

virtual void f() { }

};

class C {

public:

virtual void f() { }

};

class Drive : public A, public B, public C {

};

int main() {

Drive d;

cout << "Size is = " << sizeof(d) << endl;

return 0;

}

结果如下:Size is = 12 ,我们可以看看它的内存结构图:

虚函数可以实现函数的多态性,多态性是指用一个名字定义不同的函数,这函数执行不同但又类似的操作,从而实现“一个接口,多种方法”。C++程序在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

#include

class shape{

public:

virtual void draw(){cout<<"shape::draw()"<virtual void area(){cout<<"shape::area()"<void fun(){draw();area();}

};

class circle:public shape{

public:

void draw(){cout<<"circle::draw()"<void adjust(){cout<<"circle::adjust()"<};

main(){

shape oneshape;

oneshape.fun();

circle circleshape;

shape& baseshape=circleshape;

baseshape.fun();

}

在上面的程序中,this指针不同,从而连接到不同的fun函数。那么C++如何编译这些指令呢。道理在于:所有的基类的派生类的虚拟函数表的顺序与基类的顺序是一样的,对于基类中不存在方法再按照声明次序进行排放。这样不管是shape还是circle或者从shape又继承出来的其余的类它们的虚拟函数表的第一项总是draw函数的地址,然后是area的地址。对于circle类,下面的才是adjust的地址。因此不管对于shape还是circle,this->draw总是编译成 call this->VTABLE[0]; this->area()总是翻译成 call this->VTABLE[1]; 程序到真正运行时候将会发现this的真正指向的对象,如果是shape,则调用shape->VTABLE[0],如果是circle,则调用circle->VTABLE[1],如下图:

参考文献:
1. Zeeshan Amjad写的"ATL on the Hood”

2. 解析动态联(下)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值