C 軟體工程師面試必備

2021-10-14 23:16:09 字數 4526 閱讀 1036

拷貝建構函式與深淺拷貝

只在堆上/棧上建立物件

this指標

常函式和常物件

delete this合法嗎

為什麼空類大小不為0

靜態成員變數與靜態成員函式

初始化列表的好處和使用條件

能否通過初始化列表初始化靜態成員變數

友元全域性函式、友元類、友元成員函式

運算子過載及++過載實現

繼承方式、物件模型、同名處理

多繼承和菱形繼承

靜態函式可以是虛函式嗎

型別相容性原則 為什麼會有多型

過載、覆蓋、重寫

多型實現的基礎

靜態多型和動態多型

虛函式指標和虛函式表

函式指標與指標函式

怎麼理解多型和虛函式

建構函式能否實現多型/虛函式指標什麼時候初始化

建構函式能否是虛函式

抽象類和純虛函式

虛析構和純虛析構

為什麼析構函式必須是虛函式

為什麼c++預設的析構函式不是虛函式

類模板和函式模板

struct a;

需要對齊的原因

硬體原因:經過記憶體對齊之後,cpu的記憶體訪問速度大大提公升。訪問未對齊的記憶體,處理器要訪問兩次(資料先讀高位,再讀低位),訪問對齊的記憶體,處理器只要訪問一次,為了提高處理器讀取資料的效率,我們使用記憶體對齊

通過類建立乙個物件的過程叫例項化,例項化後使用物件可以呼叫類成員函式和成員變數,其中類成員函式稱為行為,類成員變數稱為屬性。類和物件的關係:類是物件的抽象,物件是類的例項

繼承 多型

雙冒號::作用域運算子

using分為using宣告和using編譯指令

c++的函式名稱可以重複,稱為函式過載。

建構函式和析構函式,分別對應變數的初始化和清理,變數沒有初始化,使用後果未知;沒有清理,則會記憶體管理出現安全問題。

當物件結束其生命週期,如物件所在的函式已呼叫完畢時,系統會自動執行析構函式

析構函式

拷貝建構函式的引數必須加const,因為防止修改,本來就是用現有的物件初始化新的物件。

深拷貝和淺拷貝

只有當物件的成員屬性在堆區開闢空間記憶體時,才會涉及深淺拷貝,如果僅僅是在棧區開闢記憶體,則預設的拷貝建構函式和析構函式就可以滿足要求。

我們在定義類或者結構體,這些結構的時候,最後都重寫拷貝函式,避免淺拷貝這類不易發現但後果嚴重的錯誤產生

this指標使用

void func() const //常函式,此處func為類成員函式

const person p2; //常物件

合法,但有前提:

sizeof(空class) = 1,為了確保兩個不同物件的位址不同。

若將成員變數宣告為static,則為靜態成員變數,與一般的成員變數不同,無論建立多少物件,都只有乙個靜態成員變數的拷貝,靜態成員變數屬於乙個類,所有物件共享。靜態變數在編譯階段就分配了空間,物件還沒建立時就已經分配了空間,放到全域性靜態區。

靜態成員函式

好處 不能,靜態成員變數最好類內宣告,類外初始化.靜態成員是單獨儲存的,並不是物件的組成部分。如果在類的內部進行定義,在建立多個物件時會多次宣告和定義該變數的儲存位置。在名字空間和作用域相同的情況下會導致重名的問題。

友元主要是為了訪問類中的私有成員(包括屬性和方法),會破壞c++的封裝性,盡量不使用

友元類友元成員函式

c++內建型別的後置++返回的是變數的拷貝,也就是不可修改的值;前置++返回的是變數的引用,因此可以作為修改的左值。即++(++a)或(++a)++都可以,但++(a++)不可以,(c++預設必須修改a的值,如果不修改則報錯)。

//++i

int& int::operator++()

//i++,注意後置++有佔位引數以區分跟前置++不同

const int int::operator++(int)

繼承主要是為了減少**的重複內容,解決**復用問題。通過抽象出乙個基類(父類),將重複**寫到基類中,在派生類(子類)中實現不同的方法。

子類會繼承父類的成員屬性和成員函式,但子類不會繼承父類建構函式和析構函式

多繼承會產生二義性的問題。如果繼承的多個父類中有同名的成員屬性和成員函式,在子類呼叫時,需要指定作用域從而確定父類。

兩個子類繼承於同乙個父類,同時又有另外乙個類多繼承於兩個子類,這種繼承稱為菱形繼承。比如羊和駝繼承於動物類,同時羊駝繼承於羊和駝。

使用虛繼承,在繼承方式前加virtual,這樣的話羊駝可以直接訪問m_age,不用新增作用域,且這樣操作的是共享的乙份資料

class animal;

class sheep:virtual public animal;

class camel :virtual public animal;

class son :public sheep, public camel;

void test01()

class animal;

class sheep:virtual public animal;

class camel :virtual public animal;

class son :virtual public sheep, virtual public camel;

void test01()

不可以,因為虛函式屬於物件,不屬於類,靜態函式屬於類

型別相容規則是指在需要基類物件的任何地方,都可以使用公有派生類的物件來替代,如使用子類物件可以直接賦值給父類物件或子類物件可以直接初始化父類物件時,對於同樣的一條語句,不管傳入子類還是父類物件,都是呼叫的父類函式,但我們想實現的是同樣的一條語句,傳入不同的物件,呼叫不同的函式.

class animal

};class sheep :public animal

};void dospeak(animal &animal)

//想通過父類引用指向子類物件

void test01()

但我們想傳入子類物件呼叫子類函式,傳入父類物件呼叫父類函式,即同樣的呼叫語句有多種不同的表現形態,這樣就出現了多型

重寫(overwrite):也叫做隱藏。子類重新定義父類中有相同名稱的非虛函式 ( 引數列表可以不同 ) 。如果乙個類,存在和父類相同的函式,那麼,這個類將會隱藏其父類的方法,除非你在呼叫的時候,強制轉換為父類型別或加上父類作用域

class animal

int m_age = 0;

};class sheep :public animal

int m_age = 1;

};void dospeak(animal &animal)

void test01()

void test001()

int main()

test001的函式名與myfunc函式指標都是一樣的,即都是函式指標。test001函式名是乙個函式指標常量,而myfunc是乙個函式指標變數,這是它們的關係。

虛函式的實現:在有虛函式的類中,類的最開始部分是乙個虛函式表的指標,這個指標指向乙個虛函式表,表中放了虛函式的位址,實際的虛函式在**段(.text)中。當子類繼承了父類的時候也會繼承其虛函式表,當子類重寫父類中虛函式時候,會將其繼承到的虛函式表中的位址替換為重新寫的函式位址。使用了虛函式,會增加訪問記憶體開銷,降低效率。

兩個問題本質是一樣的,建構函式不能實現多型

不能,因為在呼叫建構函式時,虛表指標並沒有在物件的記憶體空間中,必須要構造函式呼叫完成後才會形成虛表指標

在程式設計中,如果僅僅為了設計一些虛函式介面,打算在子類中對其進行重寫,那麼不需要在父類中對虛函式的函式體提供無意義的**,可以通過純虛函式滿足需求。

解決方法:將父類中的析構函式設定為虛函式,設定後會先呼叫子類析構函式,再呼叫父類析構函式

因為當發生多型時,父類指標在堆上建立子類物件,銷毀時會記憶體洩漏

因為虛函式需要額外的虛函式表和虛表指標,占用額外的記憶體。而對於不會被繼承的類來說,其析構函式如果是虛函式,就會浪費記憶體

通過template或template實現,主要用於資料的型別引數化,簡化**,有類模板和函式模板,函式模板是用於生成函式的,類模板則是用於生成類的

軟體工程師如何應對面試

軟體工程師如何應對面試 做軟體的人都討厭面試,我也一樣。可為了找工作,提薪水又不得不面對面試這一關。做軟體時間長了,人會變得內向,不太善於表達自己,可是面試是乙個自我推銷的過程。其實正確的態度是應該把面試當作軟體人的人生常態。軟體行業的特點決定了做軟體的人經常需要變換工作。即使進了微軟這樣大企業裡,...

360軟體工程師面試題

1.1億個數,找不存在的數,位圖,2.火車1423456進站出站 排列順序問題,卡特蘭數,3.copystring注意指標為空,返回位址的問題。4.有9個球,3個輕的,3個中的,3個重的,輕中重直接沒有必然的關係,比如輕 重 2 中 是不一定成立的。問稱幾次把球分成3組 5.演算法題 輸入13個不大...

面試系列(四) vivo 軟體工程師

1.自我介紹 2.問一些專案中的問題 專案介紹 遇到最大的問題等等 3.c 中的虛函式?4.程序與執行緒的區別?兩個執行緒都想去搶占臨界資源怎麼辦?什麼是死鎖?5.c語言中,堆和棧的區別?6.程序空間 32位系統下的程序空間模型,與64位下的?7.成績單,學過哪些課程?8.資料結構與演算法 9.手撕...