【C++ Primer】类的多态
一,概述
? ? ? ? 1)接口的多種不同的實(shí)現(xiàn)方式即為多態(tài)。
? ? ? ? 2)多態(tài)性是允許你將父對(duì)象設(shè)置成為和一個(gè)或更多的他的子對(duì)象相等的技術(shù),賦值之后,父對(duì)象就可以根據(jù)當(dāng)前賦值給它的子對(duì)象的特性以不同的方式運(yùn)作。簡(jiǎn)單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。多態(tài)性在C++中都是通過虛函數(shù)(Virtual Function) 實(shí)現(xiàn)的。
? ? ? ? 3)關(guān)鍵點(diǎn):多態(tài)還有個(gè)關(guān)鍵之處就是一切用指向基類的指針或引用來操作對(duì)象
二,示例
1)普通的對(duì)象操作方式
#include <iostream> using namespace std; class A{ public:void print(){ cout<<"This is A"<<endl;} }; class B:public A{ public:void print(){ cout<<"This is B"<<endl;} }; int main(){ //為了在以后便于區(qū)分,我這段main()代碼叫做main1 A a; B b; a.print();b.print(); }
輸出:This ?is ?A ??
? ? ? ? ? ?This ?is ?B
2)按照多態(tài)的操作對(duì)象方式:通過父類對(duì)象來操作子類對(duì)象
#include <iostream> using namespace std; class A{ public:void print(){ cout<<"This is A"<<endl;} }; class B:public A{ public:void print(){ cout<<"This is B"<<endl;} }; int main(){ //通過父類來操作子類 A a; B b; A* p1=&a;A* p2=&b;p1->print();p2->print(); }
輸出:This ?is ?A ??
? ? ? ? ? ?This ?is ?A
這跟我們預(yù)期的不一樣
3)采用多態(tài),就是在父類函數(shù)前面加上virtual
? ? ?根據(jù)不同的類對(duì)象,調(diào)用其相應(yīng)的函數(shù),這個(gè)函數(shù)就是虛函數(shù)
#include <iostream> using namespace std; class A{ public:virtual void print(){ cout<<"This is A"<<endl;} }; class B:public A{ public:void print(){ cout<<"This is B"<<endl;} }; int main(){ //通過父類來操作子類 A a; B b; A* p1=&a;A* p2=&b;p1->print();p2->print(); }
三,虛函數(shù)進(jìn)階
? ? ? void (A::*fun)(); //定義一個(gè)函數(shù)指針
A *p=new B;
fun=&A::fun;//是真正獲得虛函數(shù)的地址嗎? 其實(shí)間接獲得虛函數(shù)地址的一段代碼的地址
#include <iostream> using namespace std;class A{ public:virtual void fun(){ cout<<"A::fun"<<endl;}virtual void fun2(){cout<<"A::fun2"<<endl;} }; class B:public A{ public:void fun(){ cout<<"B::fun"<<endl;}void fun2(){cout<<"B::fun2"<<endl;} }; void CallVirtualFun(void *pThis , int index=0) {void (*funptr)(void*);long lVptrAddr;memcpy(&lVptrAddr,pThis,4);memcpy(&funptr,reinterpret_cast<long*>(lVptrAddr)+index,4);funptr(pThis); } int main() {void (A::*fun)(); //定義一個(gè)函數(shù)指針 A *p=new B;fun=&A::fun;//是真正獲得虛函數(shù)的地址嗎? 其實(shí)間接獲得虛函數(shù)地址的一段代碼的地址(p->*fun)();//B::fun fun = &A::fun2;(p->*fun)();//B::fun2CallVirtualFun(p); //調(diào)用虛函數(shù)p->fun() CallVirtualFun(p,1);//調(diào)用虛函數(shù)p->fun2() delete p;system("pause");return 0; }
四,補(bǔ)充重要知識(shí)
?? ? ? 實(shí)例化類的虛函數(shù)必須有定義,原因如下:有虛函數(shù)作為成員函數(shù)的類, 它的實(shí)例化-對(duì)象, 在運(yùn)行過程分配到的內(nèi)存不止是它的成員數(shù)據(jù), 還有一個(gè)指向該類虛函數(shù)表(vtable)的指針, 虛函數(shù)表中的每個(gè)數(shù)據(jù)項(xiàng)都是一個(gè)虛函數(shù)的入口地址;?
? ? ? ?如果一個(gè)對(duì)象的虛函數(shù)只有聲明而沒有實(shí)現(xiàn), 就會(huì)出現(xiàn)這個(gè)虛函數(shù)表找不到本應(yīng)作為其數(shù)據(jù)項(xiàng)之一的某函數(shù)的入口地址, 虛函數(shù)表在運(yùn)行前不能裝載完成, 所以產(chǎn)生連接錯(cuò)誤!
轉(zhuǎn)載于:https://www.cnblogs.com/secbook/archive/2012/07/10/2654976.html
總結(jié)
以上是生活随笔為你收集整理的【C++ Primer】类的多态的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 默认网关和默认路由的区别
- 下一篇: 关于c++的文件编码的研究