日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++多态讲解以及常见面试题

發(fā)布時(shí)間:2024/7/23 c/c++ 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++多态讲解以及常见面试题 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

多態(tài)的概念

什么是多態(tài)
? 多態(tài)就是在不同繼承關(guān)系的類對(duì)象,去調(diào)用同一函數(shù),產(chǎn)生了不同的行為。

實(shí)現(xiàn)多態(tài)的條件

  • 動(dòng)態(tài)綁定多態(tài)(在運(yùn)行時(shí)才知道函數(shù)的地址):
  • 調(diào)用函數(shù)的對(duì)象是指針或引用。
    被調(diào)用函數(shù)必須是虛函數(shù),并且完成了虛函數(shù)的重寫。

  • 靜態(tài)綁定多態(tài)(在編譯時(shí)確定函數(shù)的地址):
  • 函數(shù)重載

    多態(tài)的作用

    ??封裝是為了代碼模塊化,繼承是擴(kuò)展已存在的代碼,他們的目的都是為了 實(shí)現(xiàn)代碼的復(fù)用,但是多態(tài)的目的是為了實(shí)現(xiàn)接口的重用,也就是多不管傳遞過來的是哪個(gè)類對(duì)象,函數(shù)都能狗狗通過這個(gè)接口調(diào)用到適應(yīng)自己對(duì)象的實(shí)現(xiàn)方法。
    ??虛函數(shù)重寫:子類重寫父類的函數(shù)(協(xié)變:子類中的返回值和父類中的返回值是父子關(guān)系,并且是引用或指針)。如果只在父類中添加virtual關(guān)鍵字,子類中的重寫函數(shù)也會(huì)稱為虛函數(shù),童謠可以構(gòu)成多態(tài),否則為重定義。

    函數(shù)重載、重定義、重寫的區(qū)別:

  • 函數(shù)的重載:在相同的作用域中,兩個(gè)函數(shù)的參數(shù)不同,函數(shù)名相同,構(gòu)成函數(shù)重載。
  • 函數(shù)重定義:子類中有父類的同名函數(shù),繼承自父類的函數(shù)被隱藏,子類調(diào)用重寫后的。
  • 函數(shù)的重寫:子類與父類的虛函數(shù)函數(shù)名、參數(shù)、返回值相同的函數(shù),構(gòu)成函數(shù)重寫。
  • 虛函數(shù)和純虛函數(shù)

    ??虛函數(shù)就是在類的成員函數(shù)錢錢添加了virtual關(guān)鍵字。主要是為了實(shí)現(xiàn)多態(tài),通過一張?zhí)摵瘮?shù)表來實(shí)現(xiàn)。它允許子類重寫來自父類的成員函數(shù)。
    ??純虛函數(shù)就是在基類中只對(duì)對(duì)應(yīng)的虛函數(shù)進(jìn)行聲明,在最后加=0,定義純虛函數(shù)的類是一個(gè)抽象類,抽象類不能被實(shí)例化,它體現(xiàn)的是接口繼承,子類只是繼承了這個(gè)接口的形式,不需要使用他里面的功能,要實(shí)現(xiàn)自己的功能。在子類中必須實(shí)現(xiàn)父類的純虛函數(shù),如果不實(shí)現(xiàn)父類的純虛函數(shù),這個(gè)子類也是一個(gè)抽象類,同樣不能區(qū)實(shí)例化對(duì)象。
    ??那么什么是抽象類呢?抽象類就是包含純虛函數(shù)的類,這個(gè)類不能被實(shí)例化,因?yàn)轭惗x的不完整,成員函數(shù)都沒有實(shí)現(xiàn),這種類只是為了接口繼承的實(shí)現(xiàn),繼承他的子類并不想去用它,子類要實(shí)現(xiàn)自己的功能。
    ??無論是虛函數(shù)還是純虛函數(shù),都是在基類中為派生類提供編程接口,面向?qū)ο笞詈诵牡乃枷刖褪菍?duì)接口編程,而不是對(duì)實(shí)現(xiàn)編程,在C++中,就是使用繼承和多態(tài)來事項(xiàng)這種思想。如果想讓基類為派生類提供缺省的處理方法,那么就將這個(gè)函數(shù)設(shè)為虛函數(shù),如果是想讓派生類必須重寫該虛函數(shù),就將這個(gè)函數(shù)設(shè)為純虛函數(shù)。

    1、虛函數(shù)和純虛函數(shù)可以定義在同一個(gè)類中,一旦某個(gè)類包含了純虛函數(shù),這個(gè)類就是一個(gè)抽象類。
    2、虛函數(shù)可以直接被使用,但是純虛函數(shù)必須要在派生類中實(shí)現(xiàn)之后才可以使用,一i那位純虛函數(shù)在積累中只聲明沒有定義,所以無法直接使用。
    3、虛函數(shù)和純虛函數(shù)都可以在子了中被重寫,一墮胎的形式被調(diào)用。
    4、虛函數(shù)和純虛函數(shù)都是為了實(shí)現(xiàn)接口繼承而出現(xiàn)。
    5、虛函數(shù)的定義:virtual + 函數(shù)純虛函數(shù)定義:virtual + 函數(shù) + =0;
    6、虛函數(shù)和純虛函數(shù)都不能設(shè)為static,因?yàn)閟tatic在編譯的時(shí)候就要被綁定,但是虛函數(shù)和純虛函數(shù)實(shí)在運(yùn)行時(shí)在確定的。

    虛函數(shù)表

    ??虛函數(shù)表是一個(gè)函數(shù)指針數(shù)組,在末尾存放的時(shí)一個(gè)空指針nullptr,在VS中存放在代碼段,在虛函數(shù)表中只存放虛函數(shù)執(zhí)政,他不存放普通函數(shù)的指針,將新創(chuàng)建的虛函數(shù)指針存放在虛函數(shù)表末尾。
    ??虛標(biāo)指針:存放在對(duì)象模型中,在32位機(jī)上,存放在對(duì)象模型的頭4個(gè)字節(jié)中。

    單繼承中的虛表

    ??在單繼承中所有的虛函數(shù)都存放在虛表中,如果有被重寫的,直接將虛表中的虛函數(shù)指針換成重寫后的虛函數(shù)指針即可,如果在子類中的添加了新的虛函數(shù),按照新的虛函數(shù)的聲明順序?qū)⑵涮砑拥教摫碇小T谔摫碇?#xff0c;先添加父類的虛函數(shù)指針,再添加子類的虛函數(shù)指針。

    多繼承中的虛表
    #include <iostream> using namespace std; class base1 { public:virtual void func1(){cout << "base1::func1" << endl;}virtual void func2(){cout << "base1::func2" << endl;} private:int b1; }; class base2 { public:virtual void func1(){cout << "base2::func1" << endl;}virtual void func2(){cout << "base2::func2" << endl;} private:int b2; }; class derive:public base1, public base2 { public:virtual void func1(){cout << "derive::func1" << endl;}virtual void func3(){cout << "derive::func3" << endl;} private:int d1; }; typedef void(*VFPTR)(); //函數(shù)指針 void printFunc(VFPTR* vftable) {cout << "虛表地址" << vftable << endl;for (int i = 0; (*vftable) != nullptr; ++i){cout << "第" << i << "個(gè)函數(shù)地址" << *vftable << "--->";(*vftable)();//調(diào)這個(gè)函數(shù)++vftable;//指針向后走,打印下一個(gè)函數(shù)地址} }int main() {derive d;//取虛標(biāo)地址的方法://先取到d的地址,由于虛標(biāo)指針存放在對(duì)象的頭四個(gè)字節(jié)中,所以要將他轉(zhuǎn)為int*類型(int* 位四個(gè)字節(jié)),這樣就可以得到頭四個(gè)字節(jié)的內(nèi)容,對(duì)這個(gè)已經(jīng)得到的四個(gè)字節(jié)解引用就可以得到它的值,但現(xiàn)在他是整型的,我們要的是函數(shù)指針,所以要將他強(qiáng)轉(zhuǎn)位函數(shù)指針類型的指針就可以得到虛表的地址(VFPTR*)*((int*)&b);//如果要調(diào)用虛表中的第一個(gè)函數(shù),對(duì)他向后偏移1個(gè)單位再解引用就可以調(diào)用虛表中的第一個(gè)函數(shù)(*(((VFPTR*)*((int*)&b))+1))();//打印第二個(gè)虛標(biāo)地址//方法一://給出一個(gè)base2的指針,讓他存放d的地址,這時(shí)候就發(fā)生了一個(gè)天然的轉(zhuǎn)換,這個(gè)指針中存放的就是第二個(gè)虛表的地址base2* pd = &d;//方法二//讓第一個(gè)虛表的地址向后偏移base1的大小(VFPTR*)*((int*)((char*)&b+sizeof(base1)))return 0; }

    接口繼承和實(shí)現(xiàn)繼承

    ??普通函數(shù)的繼承就是一種實(shí)現(xiàn)繼承,派生類繼承了基類函數(shù),繼承的是函數(shù)的實(shí)現(xiàn)。
    ??虛函數(shù)的繼承是接口繼承,派生類繼承的是基類函數(shù)的接口,目的是為了重寫,從而達(dá)成多態(tài),繼承的是接口。如果不是為了實(shí)現(xiàn)多態(tài),不要把函數(shù)設(shè)為虛函數(shù)。

    —>常見面試題<—

    總結(jié)

    以上是生活随笔為你收集整理的C++多态讲解以及常见面试题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。