C++多态面试题汇总
總結(jié)了一些常見的面試題,通過查閱資料給出了一些淺薄的解析,歡迎各位批評指教。
1. inliine函數(shù)可以實虛函數(shù)碼?
不可以,因為inline函數(shù)沒有地址,無法將他存放到虛函數(shù)表中。
2. 靜態(tài)成員可以是虛函數(shù)嗎?
不能,因為靜態(tài)成員函數(shù)中沒有this指針,使用::成員函數(shù)的嗲用用方式無法訪問虛函數(shù)表,所以靜態(tài)成員函數(shù)無法放進虛函數(shù)表。
3. 構(gòu)造函數(shù)可以是虛函數(shù)嗎?
不可以,因為對象中的虛函數(shù)指針是在對象構(gòu)造的時候初始化的。
4. 析構(gòu)函數(shù)可以是虛函數(shù)嗎?什么場景下析構(gòu)函數(shù)是虛函數(shù)?
可以,最好將析構(gòu)函數(shù)設(shè)置為虛函數(shù)最好是將父類的析構(gòu)函數(shù)設(shè)置為虛函數(shù) ,因為這樣可以避免內(nèi)存泄漏的問題。如果一個父類的指針指向了子類的的對象,并且父類的虛函數(shù)沒有設(shè)置成虛函數(shù),那么子類對象中的虛函數(shù)就沒有實現(xiàn)多態(tài),他只會調(diào)用父類的析構(gòu)函數(shù),不會調(diào)用子類的析構(gòu)函數(shù),但是他創(chuàng)建對象的時候調(diào)用了子類的構(gòu)造函數(shù),所以說就用子類的構(gòu)造函數(shù)就應(yīng)該該取調(diào)用他的析構(gòu)函數(shù),這樣才能保證所有的必須釋放的資源都是放了,才可以保證不會有內(nèi)存泄漏。如果是多態(tài)的,就會先去調(diào)用子類的析構(gòu)函數(shù),然后再取調(diào)用父類的析構(gòu)函數(shù),這樣子類和父類的資源就都可以釋放。
5. 對象訪問普通函數(shù)快還是虛函數(shù)快?
如果是普通對象,是一樣快的,如果是指針對象或者是引用對象,調(diào)用普通函數(shù)更快一些,因為構(gòu)成了多態(tài),運行時調(diào)用虛函數(shù)要先到虛函數(shù)表中去查找。這樣然后才拿到韓式的地址,這樣就不如直接可以拿到函數(shù)地址的普通函數(shù)快。
6. 虛函數(shù)表時再什么階段生成的?他存放在哪里?
虛函數(shù)時再編譯階段生成的,他一般存放再代碼段,也就是常量區(qū)。
7. 執(zhí)行下面這段代碼的結(jié)果
#include <iostream> using namespace std;class Base { public:virtual void x(){cout << "Base::x" << endl;}void y(){x();cout << "Base::y" << endl;} };class Derive : public Base { public:virtual void x(){cout << "Derive::x" << endl;}void y(){cout << "Derive::y" << endl;} };int main() {Base* p = new Derive;p->y();return 0; }解析:很顯然Derive繼承了Base,并且實現(xiàn)了多態(tài),但是只有x()是虛函數(shù)重寫,y()只在子類中聲明了虛函數(shù),沒有在父類中聲名所以不能y()不是虛函數(shù)重寫,而是對父類中的y()重定義,所以在p調(diào)用y()的時候直接調(diào)用Base中的y(),在Base的y()中調(diào)用了x(),由于x()在子類中構(gòu)成了虛函數(shù)重寫,所以調(diào)用子類中的x(),答案也就不曉而知了。
8. 是否可以將類中的所有成員函數(shù)都聲明稱為虛函數(shù),為什么?
虛函數(shù)是在程序運行的時候通過尋址操作才能確定真正要調(diào)用的的函數(shù),而普通的成員函數(shù)在編譯的時候就已經(jīng)確定了要調(diào)用的函數(shù)。這個兩者的區(qū)別,從效率上來說,虛函數(shù)的效率要低于普通成員函數(shù),因為虛函數(shù)要先通過對象中的虛標(biāo)指針拿到虛函數(shù)表的地址,然后再從虛函數(shù)表中找到對應(yīng)的函數(shù)地址,最后根據(jù)函數(shù)地址去調(diào)用,而普通成員函數(shù)直接就可以拿到地址進行調(diào)用,所以沒必要將所有的成員函數(shù)聲明成虛函數(shù)。
9. 虛函數(shù)表指針被編譯器初始化的過程怎么理解的?
當(dāng)類中聲明了虛函數(shù)是,編譯器會在類中生成一個虛函數(shù)表VS中存放在代碼段,虛函數(shù)表實際上就是一個存放虛函數(shù)指針的指針數(shù)組,是由編譯器自動生成并維護的。虛表是屬于類的,不屬于某個具體的對象,一個類中只需要有一個虛表即可。同一個類中的所有對象使用同一個虛表,為了讓每個包含虛表的類的對象都擁有一個虛表指針,編譯器在每個對象的頭添加了一個指針,用來指向虛表,并且這個指針的值會自動被設(shè)置成指向類的虛表,每一個virtaul函數(shù)的函數(shù)指針存放在虛表中,如果是單繼承,先將父類的虛表添加到子類的虛表中,然后子類再添加自己新增的虛函數(shù)指針,但是在VS編譯器中我們通常看不到新添加的虛函數(shù)指針,是編譯器故意將他們隱藏起來,如果是多繼承,在子類中新添加的虛函數(shù)指針會存放在第一個繼承父類的虛函數(shù)表中。
10. 多態(tài)的分類?
靜態(tài)綁定的多態(tài)的是通過函數(shù)的重載來實現(xiàn)的。動態(tài)綁定的多態(tài)是通過虛函數(shù)實現(xiàn)的。
11. 為什么要引入抽象類和純虛函數(shù)?
為了方便使用多態(tài)特性,在很多情況下由基類生成對象是很不合理的,純虛函數(shù)在基類中是沒有定義的,要求在子類必須加以實現(xiàn),這種包含了純虛函數(shù)的基類被稱為抽象類,不能被實例化,如果子類沒有實現(xiàn)純虛函數(shù),那么它他也是一個抽象類。
12. 虛函數(shù)和純虛函數(shù)有什么區(qū)別?
從基類的角度出發(fā),如果一個類中聲明了虛函數(shù),這個函數(shù)是要在類中實現(xiàn)的,它的作用是為了能讓這個函數(shù)在他的子類中能被重寫,實現(xiàn)動態(tài)多態(tài)。純虛函數(shù),只是一個接口,一個函數(shù)聲明,并沒有在聲明他的類中實現(xiàn)。對于子類來說它可以不重寫基類中的虛函數(shù),但是他必須要將基類中的純虛函數(shù)實現(xiàn)。虛函數(shù)既繼承接口的同時也繼承了基類的實現(xiàn),純虛函數(shù)關(guān)注的是接口的統(tǒng)一性,實現(xiàn)完全由子類來完成。
13. 什么是多態(tài)?他有什么作用?
多態(tài)就是一個接口多種實現(xiàn),多態(tài)是面向?qū)ο蟮娜筇匦灾弧6鄳B(tài)分為靜態(tài)多態(tài)和動態(tài)多態(tài)。靜態(tài)多態(tài)包含函數(shù)重載和泛型編程,進程多態(tài)是程序調(diào)用函數(shù),編譯器決定使用哪個可執(zhí)行的代碼塊。靜態(tài)多態(tài)是由繼承機制以及虛函實現(xiàn)的,通過指向派生類的基類指針或者引用,訪問派生類中同名重寫成員函數(shù)。墮胎的作用就是把不同子類對象都當(dāng)作父類來看,可以屏蔽不同子類之間的差異,從而寫出通用的代碼,做出通用的編程,以適應(yīng)需求的不斷變化。
總結(jié)
以上是生活随笔為你收集整理的C++多态面试题汇总的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【每日SQL打卡】
- 下一篇: C++常见面试题(2019年校招总结)