浅析C++多态及其实现模式
一. 多态的实现--虚表
1.多态就是多种形态。在C++中,对同一父类和子类构造出的不同对象发出同一条指令,需要它们完成不同的工作,就需要在父类和子类写出相同函数名的函数方法,并用虚函数区分它们。父类的指针/引用调用重写的虚函数,当父类指针/引用指向父类对象时调用的是父类的虚函数,指向子类对象时调用的是子类的虚函数。
2.虚函数表是通过一块连续内存来存储虚函数的地址。这张表解决了继承、虚函数(重写)的问题。在有虚函数的对象实例中都存在一张虚函数表,虚函数表就像一张地图,指明了实际应该调用的虚函数函数。
//带虚函数的类classBase{public:virtualvoidfunc1(){cout<<"Base::func1()"<<endl;}virtualvoidfunc2(){cout<<"Base::func2()"<<endl;}private:inta;};voidTest1(){Baseb1;}
3.带虚函数的类的模型结构
4.同一类的对象共用同一虚表
voidTest2(){Baseb1,b2,b3;}
二. 单继承&多继承的对象模型
1.单继承:
classBase{public:virtualvoidfunc1(){cout<<"Base::func1()"<<endl;}virtualvoidfunc2(){cout<<"Base::func2()"<<endl;}private:inta;};classDerive:publicBase{public:virtualvoidfunc1(){cout<<"Derive::func1"<<endl;}virtualvoidfunc3(){cout<<"Derive::func3"<<endl;}virtualvoidfunc4(){cout<<"Derive::func4"<<endl;}private:intb;};typedefvoid(*FUNC)();voidPrintVTable(int*VTable){cout<<"虚表地址>"<<VTable<<endl;for(inti=0;VTable[i]!=0;++i){printf("第%d个虚函数地址:0X%x,->",i,VTable[i]);FUNCf=(FUNC)VTable[i];f();}cout<<endl;}voidTest1(){Baseb1;Derived1;int*VTable1=(int*)(*(int*)&b1);int*VTable2=(int*)(*(int*)&d1);PrintVTable(VTable1);PrintVTable(VTable2);}
2.多继承
classBase1{public:virtualvoidfunc1(){cout<<"Base1::func1"<<endl;}virtualvoidfunc2(){cout<<"Base1::func2"<<endl;}private:intb1;};classBase2{public:virtualvoidfunc1(){cout<<"Base2::func1"<<endl;}virtualvoidfunc2(){cout<<"Base2::func2"<<endl;}private:intb2;};classDerive:publicBase1,publicBase2{public:virtualvoidfunc1(){cout<<"Derive::func1"<<endl;}virtualvoidfunc3(){cout<<"Derive::func3"<<endl;}private:intd1;};typedefvoid(*FUNC)();voidPrintVTable(int*VTable){cout<<"虚表地址>"<<VTable<<endl;for(inti=0;VTable[i]!=0;++i){printf("第%d个虚函数地址:0X%x,->",i,VTable[i]);FUNCf=(FUNC)VTable[i];f();}cout<<endl;}voidTest1(){Derived1;int*VTable=(int*)(*(int*)&d1);PrintVTable(VTable);//Base2虚函数表在对象Base1后面VTable=(int*)(*((int*)&d1+sizeof(Base1)/4));PrintVTable(VTable);}
三. 静态多态和动态多态
1.静态多态就是重载,因为是在编译期决议确定,所以称为静态多态。
2.动态多态就是通过继承重写基类的虚函数实现的多态,因为是在运行时决议确定,所以称为动态多态。
classBase{public:virtualvoidfunc1(){cout<<"Base::func1"<<endl;}virtualvoidfunc2(){cout<<"Base::func2"<<endl;}voiddisplay(){cout<<"display()"<<endl;}voiddisplay(inti){cout<<"display(inti)->"<<i<<endl;}private:inta;};classDerive:publicBase{public:virtualvoidfunc1(){cout<<"Derive::func1"<<endl;}virtualvoidfunc3(){cout<<"Derive::func3"<<endl;}virtualvoidfunc4(){cout<<"Derive::func4"<<endl;}private:intb;};voidfunc(Base&b){b.func1();b.display();b.display(10);}voidTest1(){Baseb1;Derived1;func(b1);func(d1);}
四. 菱形虚拟继承的对象模型
classA{public:virtualvoidFunTest1(){cout<<"A::FunTest1()"<<endl;}virtualvoidFunTest2(){cout<<"A::FunTest2()"<<endl;}private:int_a;};classB1:virtualpublicA{public:virtualvoidFunTest3(){cout<<"B1::FunTest3()"<<endl;}virtualvoidFunTest4(){cout<<"B2::FunTest4()"<<endl;}private:int_b1;};classB2:virtualpublicA{public:virtualvoidFunTest1(){cout<<"B2::FunTest1()"<<endl;}virtualvoidFunTest4(){cout<<"B2::FunTest4()"<<endl;}private:int_b2;};classC:publicB1,publicB2{public:virtualvoidFunTest1(){cout<<"C::FunTest1()"<<endl;}virtualvoidFunTest5(){cout<<"C::FunTest5()"<<endl;}private:int_c;};voidTest1(){Cc;c.FunTest5();}
可见,在虚拟继承中,无论是几重继承,最终子类的虚函数表总是与继承列表的第一个父类的虚函数表合并在一起,但是有覆盖的虚函数,自然去覆盖父类的同名虚函数,并合并在该父类的虚表中。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。