Polymorphism & Virtual Function
关于C++多态,看下面的例子:
#include <iostream>
using namespace std;
class Shape
{
public:
virtual void print(){cout << "Call print()" << endl;}
virtual void draw(){cout << "Call Shape::draw()" << endl;}
};
class Circle : public Shape
{
public:
Circle(){cout<< "Call Circle Constructor !" << endl;}
void draw(){cout << "Call Circle::draw()" << endl;}
void print(){cout << "Call Circle::print()" << endl;}
};
class Square : public Shape
{
public:
Square(){cout<< "Call Square Constructor !" << endl;}
void draw(){cout << "Call Square::draw()" << endl;}
};
class Triangle : public Shape
{
public:
Triangle(){cout<< "Call Triangle Constructor !" << endl;}
void draw(){cout << "Call Triangle::draw()" << endl;}
};
int main()
{
typedef void(*Fun)(void);
Fun pFun = NULL;
Shape *A[]={new Circle,new Square,new Triangle};
Shape *Temp = new Circle;
Temp->draw();
pFun = (Fun)*((int*)*(int*)(Temp));
cout << "(int*)(Temp) " << (int*)(Temp) << endl;
cout << "*(int*)(Temp) " << *(int*)(Temp) << endl;
cout << "(int*)*(int*)(Temp) " << (int*)*(int*)(Temp) << endl;
cout << "(Fun)*((int*)*(int*)(Temp)) " << (Fun)*((int*)*(int*)(Temp)) << endl;
cout << pFun << endl;
pFun();
Circle Cir;
Cir.draw();
pFun = (Fun)*((int*)*(int*)(&Cir));
pFun();
Shape Sh;
Sh.draw();
return 0;
}
输出为:
Call Circle Constructor !
Call Square Constructor !
Call Triangle Constructor !
Call Circle Constructor !
Call Circle::draw()
(int*)(Temp) 003965D8
*(int*)(Temp) 4290792
(int*)*(int*)(Temp) 004178E8
(Fun)*((int*)*(int*)(Temp)) 004112D0
004112D0
Call Circle::print()
Call Circle Constructor !
Call Circle::draw()
Call Circle::print()
Call Shape::draw()
调试变量的内容为:
Temp 0x00393ad0
[Circle] {...}
Shape {...}
__vfptr 0x004178e8 const Circle::'vftable'
[0x0] 0x004112d0 Circle::print(void)
[0x1] 0x00411005 Circle::draw(void)
Cir {...} Circle
Shape {...} Shape
__vfptr 0x004178e8 const Circle::`vftable'
[0x0] 0x004112d0 Circle::print(void)
[0x1] 0x00411005 Circle::draw(void)
Sh {...} Shape
__vfptr 0x00417bf0 const Shape::`vftable'
[0x0] 0x004112c6 Shape::print(void)
[0x1] 0x00411145 Shape::draw(void)
由调试结果可以看出:
Shape *Temp = new Circle; 和Circle Cir; 即Temp和Cir他们的虚函数列表(vtbl)是一样的,他们的虚函数指针(vptr)同指向一个虚函数列表(0x004178e8 const Circle::`vftable')。
当基类有虚函数时每一个子类都有自己的虚函数列表,而且子类的虚函数列表中的函数会覆盖基类的虚函数。当多态的情况发生时,编辑器会动态的绑定对象所要调用的虚函数,比如: Shape *Temp = new Circle; Temp->draw(); 这个Temp->draw();就是在运行时动态的绑定所要调用的虚函数,根据Circle虚函数列表来确定要调用的函数。