文章目錄
- 1.c++面向對象三大特性
- 2.c++的三個訪問修飾符
- 3.多重繼承
- 4.重載與重寫
- 5.c++多態怎么實現
- 6.成員函數/成員變量/靜態成員函數/靜態成員變量的區別
- 7.構造函數和析構函數
- 8.c++構造函數有幾種
- 9.什么是虛函數什么是虛函數表
- 10.虛函數和純虛函數的區別
- 11.抽象類和純虛函數
- 12.虛析構
- 13.為什么要虛析構,為什么不能虛構造
- 14.那些函數不能被聲明為虛函數
- 15.淺拷貝和深拷貝的區別
- 參考
1.c++面向對象三大特性
- 面向對象:對象是指具體的某一個事物,這些事物的抽象就是類,類中包含數據(成員變量)和動作(成員方法)。
- 面向對象的三大特性:
- 封裝:將具體的實現過程和數據封裝成一個函數,只能通過接口進行訪問,降低耦合性。
- 繼承:讓某種類型對象獲得另?個類型對象的屬性和?法。
- 多態:多態就是不同繼承類的對象,對同一消息做出不同的響應,基類的指針指向或綁定到派生類的對象,使得基類指針呈現不同的表現方式。
- 實現多態有兩種?式
覆蓋(override): 是指?類重新定義?類的虛函數的做法
重載(overload): 是指允許存在多個同名函數,?這些函數的參數表不同(或許參數個數不同,或許參數類型不同,或許兩者都不同)
- 實現多態有兩種?式
2.c++的三個訪問修飾符
public 、 private 和 protected 。
這些修飾符決定了類中的成員對外部代碼的可?和訪問權限
- public 修飾符?于指定類中的成員可以被類的外部代碼訪問。公有成員可以被類外部的任何代碼(包括類的實例)訪問。
- private 修飾符?于指定類中的成員只能被類的內部代碼訪問。私有成員對外部代碼是不可?的,只有類內部的成員函數可以訪問私有成員。
- protected 修飾符?于指定類中的成員可以被類的派?類訪問。受保護成員對外部代碼是不可?的,但可以在派?類中被訪問。
3.多重繼承
?個類可以從多個基類(?類)繼承屬性和?為。
在C++等?持多重繼承的語?中,
?個派?類可以同時擁有多個基類。
多重繼承可能引??些問題,如菱形繼承問題, ?如當?個類同時繼承了兩個擁有相同基類的類,?最終的派?類?同時繼承了這兩個類時, 可能導致?義性和代碼設計上的復雜性。為了解決這些問題,C++ 提供了虛繼承, 通過在繼承聲明中使? virtual 關鍵字,可以避免在派?類中?成多個基類的實例,從?解決了菱形繼承帶來的?義性。
4.重載與重寫
-
重載:重載是指在同?作?域內,使?相同的函數名但具有不同的參數列表或類型,使得同?個函數名可以有多個版本。
-
重寫:重寫是指派?類(?類)重新實現(覆蓋)基類(?類)中的虛函數,以提供特定于派?類的實現。重寫是?向對象編程中的多態性的?種體現,主要涉及基類和派?類之間的關系,?于實現運?時多態。
-
區別
重寫 | 重載 | |
---|---|---|
范圍 | 重寫發生在不同的類之間(子類和父類之間) | 重載發生在同一個類的內部 |
參數 | 重寫的函數的函數名、參數列表和返回值類型都需要和原函數相同,父類中被重寫的函數需要有 virtual 修飾 | 重載的函數需要與原函數有相同的函數名、不同的參數列表,不關注函數的返回值類型 |
vritual關鍵字 | 必須有 | 可以有,可以沒有 |
5.c++多態怎么實現
- 多態概念:多態就是不同繼承類的對象,對同一消息做出不同的響應,基類的指針指向或綁定到派生類的對象,使得基類指針呈現不同的表現方式。在基類的函數前加上 virtual 關鍵字,在派生類中重寫該函數,運行時將會根據對象的實際類型來調用相應的函數。如果對象類型是派生類,就調用派生類的函數;如果對象類型是基類,就調用基類的函數。
- 多態實現原理:多態是通過虛函數實現的,虛函數的地址保存在虛函數表中,虛函數表的地址保存在含有虛函數的類的實例對象的內存空間中。
- 簡單解釋:當基類的指針指向派生類的對象時,通過派生類的對象的虛表指針找到虛函數表(派生類的對象虛函數表),進而找到相應的虛函數進行調用。
6.成員函數/成員變量/靜態成員函數/靜態成員變量的區別
-
成員函數:
- 成員函數是屬于類的函數,它們可以訪問類的成員變量和其他成員函數。
- 成員函數可以分為普通成員函數和靜態成員函數。
- 普通成員函數使?對象調?,可以訪問對象的成員變量。
- 普通成員函數的聲明和定義通常在類的內部,但定義時需要使?類名作為限定符。
-
成員變量:
- 成員變量是屬于類的變量,存儲在類的每個對象中。
- 每個對象擁有?份成員變量的副本,它們在對象創建時分配,并在對象銷毀時釋放。
- 成員變量的訪問權限可以是 public 、 private 或 protected 。
-
靜態成員函數:
- 靜態成員函數屬于類?不是對象,因此可以直接通過類名調?,?不需要創建類的實例。
- 靜態成員函數不能直接訪問普通成員變量,因為它們沒有隱含的 this 指針。
- 靜態成員函數的聲明和定義也通常在類的內部,但在定義時需要使?類名作為限定符。
-
靜態成員變量:
- 靜態成員變量是屬于類?不是對象的變量,它們在所有對象之間共享。
- 靜態成員變量通常在類的聲明中進?聲明,但在類的定義外進?定義和初始化。
- 靜態成員變量可以通過類名或對象訪問。
7.構造函數和析構函數
- 構造函數:構造函數是在創建對象時?動調?的特殊成員函數。它的主要?的是初始化對象的成員變量,為對象分配資源,執?必要的初始化操作。
- 析構函數:析構函數是在對象?命周期結束時?動調?的特殊成員函數。它的主要?的是釋放對象占?的資源、執?必要的清理操作。
8.c++構造函數有幾種
- 默認構造:沒有任何參數的構造函數。如果?戶沒有為類定義構造函數,編譯器會?動?成?個默認構造
函數。默認構造函數?于創建對象時的初始化,當?戶不提供初始化值時,編譯器將調?默認構造函數。 - 帶參構造:接受?個或多個參數,?于在創建對象時傳遞初始化值。
- 拷貝構造:?于通過已存在的對象創建?個新對象,新對象是原對象的副本。參數通常是對同類型對象的
引?。 - 委托構造函數:在?個構造函數中調?同類的另?個構造函數,減少代碼重復。
9.什么是虛函數什么是虛函數表
-
虛函數:C++中的虛函數的作?主要是實現了多態的機制。虛函數允許在派?類中重新定義基類中定義的函數,使得通過基類指針或引?調?的函數在運?時根據實際對象類型來確定。這樣的機制被稱為動態綁定或運?時多態。
在基類中,通過在函數聲明前?加上 virtual 關鍵字,可以將其聲明為虛函數。派?類可以重新定義虛函數,如果派?類不重新定義,則會使?基類中的實現。 -
虛函數表:虛函數的實現通常依賴于?個被稱為虛函數表(虛表)的數據結構。每個類(包括抽象類)都有?個虛表,其中包含了該類的虛函數的地址。每個對象都包含?個指向其類的虛表的指針,這個指針被稱為虛指針(vptr)。
當調??個虛函數時,編譯器會使?對象的虛指針查找虛表,并通過虛表中的函數地址來執?相應的虛函數。這就是為什么在運?時可以根據實際對象類型來確定調?哪個函數的原因。
10.虛函數和純虛函數的區別
-
虛函數
- 有實現: 虛函數有函數聲明和實現,即在基類中可以提供默認實現。
- 可選實現: 派?類可以選擇是否覆蓋虛函數。如果派?類沒有提供實現,將使?基類的默認實現。
- 允許實例化: 虛函數的類可以被實例化。即你可以創建?個虛函數的類的對象。
- 調?靠對象類型決定: 在運?時,根據對象的實際類型來決定調?哪個版本的虛函數。
- ? virtual 關鍵字聲明:虛函數使? virtual 關鍵字聲明,但不包含 = 0 。
-
純虛函數:
- 沒有實現: 純虛函數沒有函數體,只有函數聲明,即沒有提供默認的實現。
- 強制覆蓋: 派?類必須提供純虛函數的具體實現,否則它們也會成為抽象類。
- 禁?實例化: 包含純虛函數的類?法被實例化,只能?于派?其他類。
- ? = 0 聲明: 純虛函數使? = 0 在函數聲明末尾進?聲明。
- 為接?提供規范: 通過純虛函數,抽象類提供?種接?規范,要求派?類提供相關實現。
11.抽象類和純虛函數
- 抽象類:是不能被實例化的類,它存在的主要?的是為了提供?個接?,供派?類繼承和實現。抽象類中可以包含普通的成員函數、數據成員和構造函數,但它必須包含?少?個純虛函數。即在聲明中使? virtual 關鍵字并賦予函數?個 = 0 的純虛函數。
- 純虛函數:是在抽象類中聲明的虛函數,它沒有具體的實現,只有函數的聲明。通過在函數聲明的末尾使? = 0 ,可以將虛函數聲明為純虛函數。派?類必須實現抽象類中的純虛函數,否則它們也會成為抽象類。
12.虛析構
虛析構函數是?個帶有 virtual 關鍵字的析構函數。 主要作?是確保在通過基類指針刪除派?類對象時,能夠正確調?派?類的析構函數,從?釋放對象所占?的資源。
通常,如果?個類可能被繼承,且在其派?類中有可能使? delete 運算符來刪除通過基類指針指向的對象,那么該基類的析構函數應該聲明為虛析構函數。
13.為什么要虛析構,為什么不能虛構造
虛析構函數允許在運?時根據對象的實際類型調?正確的析構函數,從?實現多態性。如果基類的析構函數不是虛的,當通過基類指針刪除指向派?類對象的對象時,只會調?基類的析構函數,?不會調?派?類的析構函數。這可能導致派?類的資源未被正確釋放,造成內存泄漏。
構造函數在對象的創建階段被調?,對象的類型在構造函數中已經確定。因此,構造函數調?不涉及多態性,也就是說,在對象的構造期間?法實現動態綁定。虛構造函數沒有意義,因為對象的類型在構造過程中就已經確定,不需要動態地選擇構造函數。
14.那些函數不能被聲明為虛函數
常?的不不能聲明為虛函數的有:
普通函數(?成員函數),靜態成員函數,
內聯成員函數,構造函數,友元函數。
15.淺拷貝和深拷貝的區別
主要區別在于如何處理對象內部的動態分配的資源。
-
深拷貝:該對象和原對象占用不同的內存空間,既拷貝存儲在棧空間中的內容,又拷貝存儲在堆空間中的內容。
-
淺拷貝:該對象和原對象占用同一塊內存空間,僅拷貝類中位于棧空間中的內容。
參考
Leetcodec++面試突破
代碼隨想錄–最強八股文c++