使用函数指针模拟C++多态
1 #include <iostream> 2 using namespace std; 3 4 class Base 5 { 6 public : 7 void display() 8 { 9 cout << "Base display" << endl; 10 } 11 12 void (Base :: **VTable)();//指向虚表的函数指针 13 int a; 14 }; 15 16 class Derived : public Base 17 { 18 public : 19 void display() 20 { 21 cout << "derived display" << endl; 22 } 23 }; 24 25 void test(Base *pointer) 26 { 27 void (Base :: *pFunc)() = (void(Base :: *)())pointer->VTable[0]; 28 (pointer->*pFunc)(); 29 } 30 31 int main() 32 { 33 //多态是通过多余的存储空间存储了虚函数的地址,通过函数指针来实现虚函数的调用 34 //1.分配空间+4,成员变量从+4的位置开始了。最上面的控件保留一个指针。 35 //2.为该指针指向的地址分配一块存储空间 36 //3.将所有虚函数的地址存储到这块存储空间中,这个存储空间称为虚表
//初始化工作,也就是编译器帮我们做的事 37 Derived *derived = new Derived(); 38 derived->VTable = (void(Base :: **)())new int[1]; 39 derived->VTable[0] =(void(Base :: *)()) &Derived :: display;//初始化工作 40 test(derived); 41 42 Base *base = new Base(); 43 base->VTable = (void(Base :: **)())new int[1]; 44 base->VTable[0] = (void(Base :: *)()) &Base :: display; 45 test(base);
48 system("pause"); 49 return 0; 50 }
基类如果不使用虚函数virtual构成多态的话,使用sizeof得到Base的大小为4,如下图(Base中的成员变量只有一个int a,使用32位编译器,如下代码中的基类,只是演示使用)
1 #include <iostream> 2 using namespace std; 3 4 class Base 5 { 6 public : 7 void display() 8 { 9 cout << "Base display" << endl; 10 } 11 12 int a; 13 }; 14 15 class Derived : public Base 16 { 17 public : 18 void display() 19 { 20 cout << "derived display" << endl; 21 } 22 }; 23 24 int main() 25 { 26 cout << "Base's size is " << sizeof(Base) << endl; 27 system("pause"); 28 return 0; 29 }
如果使用virtual构成虚函数,再使用sizeof测试基类的大小,会发现基类大小增加了4
#include <iostream> using namespace std; class Base { public : virtual void display() { cout << "Base display" << endl; } int a; }; class Derived : public Base { public : void display() { cout << "derived display" << endl; } }; int main() { cout << "Base's size is " << sizeof(Base) << endl; system("pause"); return 0; }
那这个 4byte的空间是什么东西?是干什么用?
经过向父类加入多个虚函数,测试之后发现还是只是增加4byte,那么只有指针可以做到。
这个指针是一个二级指针,指向一个虚表的地址,虚表中存储的是父类与子类同名函数的地址。(比较复杂,我也只能理解到这个地步,所以表达更是low)
/**********************************************************************************2017/7/20,以后有了更深的理解再继续更新******************************************************************************************/