1. 程式人生 > >C++筆、面試常見題之一二

C++筆、面試常見題之一二

我們一定要堅信,在堅持中才能看到希望,而不是看到希望後才開始堅持

Q1:問請用簡單語句告訴我C++是什麼?

C++是在C語言的基礎上開發的一種面向物件程式語言,應用廣泛。C++融合了3種不同的程式設計方式:C語言代表的過程性語言、C++在C語言基礎上新增的類代表的面嚮物件語言、C++模板支援的泛型程式設計。其程式設計領域眾廣,常用於系統開發、引擎開發等應用領域,是最受廣大程式設計師受用的最強大程式語言之一,支援類及繼承、封裝和多型等特性

Q2:C和C++的區別?

C++在C的基礎上增添類,C是一個結構化語言,它的重點在於演算法和資料結構。C程式的設計首要考慮的是如何通過一個過程,對輸入(或環境條件)進行運算處理得到輸出(或實現過程(事務)控制)。而對於C++,首要考慮的是如何構造一個物件模型,讓這個模型能夠契合與之對應的問題域,這樣就可以通過獲取物件的狀態資訊得到輸出或實現過程(事務)控制。

Q3:什麼是面向物件(OOP)?

面向物件是一種對現實世界理解和抽象的方法、思想,通過將需求要素等轉化為物件進行問題處理的思想。面向物件程式設計的本質是設計並擴充套件自己的資料型別。
用一張圖展示就是:
圖片

Q3:指標和引用的區別?

序 號 描述 指標 引用
1 定義 是一個變數,儲存的是一個記憶體地址 變數的別名
2 初始化 可以為空值 不可以為空值,且必須初始化
3 多級 可以多級 只能一級
4 改變值 初始化後可以改變,即指向其他的儲存單元 初始化後不可以再改變
5 sizeof 得到的是指標本身的大小 所指向的變數的大小
6 記憶體分配 指標需要分配記憶體空間 引用不需要分配
7 解引用 指標需要解引用 引用無需解引用

注:解引用就可以理解為“解碼”的意思。假設ptr裡面存放的是一個記憶體地址,那麼 * ptr就是這個記憶體地址裡面存放的資料。前面這個“* ”的解引用操作,就可以理解為對這個ptr進行解碼,解碼得到的資料就是* ptr,也就是我們常說的“這個記憶體地址裡面存放的資料”或者“這個指標指向的資料”。“指標”的理解模式太容易混淆,而“解碼”的理解模式更好記一點。

Q4:const在函式中可以作用在哪些地方,意義分別是啥?

const int num(int x);代表num函式的返回值是int型別的常量
int num(int x) const;代表的num函式不能隱形的修改引數x的值
int num(const int x);代表引數x是常量,不可以修改

Q5:new/delete 和 malloc/free 的區別?

  • 相同點:都是申請記憶體和釋放記憶體
  • 本質區別:malloc/free是C/C++ 語言的標準庫函式,new/delete是C++的運算子。
    對於使用者自定義的物件而言,用malloc/free無法滿足動態管理物件的要求。物件在建立的同時要自動執行建構函式,物件在消亡之前要自動執行解構函式。由於malloc/free是庫函式不是運算子,不在編譯器的控制範圍之內,不能夠把執行建構函式和解構函式的任務強加給malloc/free,因此C++需要一個能完成動態記憶體分配和初始化工作的運算子new,以及一個能完成清理和釋放記憶體工作的運算子delete。
  • 聯絡:C++程式要經常呼叫C函式,而C程式只能呼叫malloc/free管理動態記憶體。因此兩者要共存。

Q6:友元的作用?

友元分為友元類和友元函式。
特點:是一種定義在類外部的普通函式或者類,但他需要在類內部進行說明。為了和類的成員函式進行區分,在說明的前面加以 friend關鍵字。友元不是成員函式,但是他可以訪問類的私有成員。友元的作用是提高程式的執行效率,但是他破壞了程式的封裝性和隱藏性。使得非成員函式可以方位類的私有成員。

Q7:虛解構函式的作用?

一般情況下,類的解構函式裡面都是釋放記憶體資源,而解構函式不被呼叫的話,就會發生記憶體洩漏。當然並不是把所有的解構函式都寫成虛解構函式,因為當類裡面有虛擬函式的時候,編譯器會給類新增一個虛擬函式表,裡面用來存放虛擬函式的指標,從而增加的類的空間。所有隻有當類為基類時,才將解構函式寫成虛解構函式。

Q8:虛繼承的作用?

基本原則是在記憶體中只有基類成員的一份拷貝。這樣通過把基類繼承宣告為虛擬的,就只能繼承基類的一份拷貝,從而消除歧義。
class A : virtual class B{
};

Q9:巨集定義的特點和實現,行內函數取代他的意義

  • 巨集定義在形式和使用上像一個函式,但他使用前處理器實現,沒有了引數壓棧、程式碼生成等一系列操作。因此效率很高。
  • 雖然效率高,但是是在前處理器中實現的,所以不能進行引數的有效檢測,也就不能享受C++編譯器嚴格型別檢查的好處,另外返回值也不能強制轉換成可轉換的合適的型別。
  • C++中引入了類和類的訪問控制,這樣如果一個表示式涉及到類的保護成員或者私有成員,就不能用巨集定義來實現。
  • 正因為如此,引入了行內函數。行內函數的程式碼被放入到符號表中,在使用時直接進行替換,沒有了展開的開銷,效率也很高。
  • 類的行內函數也是一個真正的函式,編譯器在呼叫一個行內函數時,會首先檢查他的引數型別,保證呼叫正確。消除了隱患和侷限性。
  • 內斂函式可以作為某個類的成員函式,當然就可以在其中使用所在類的保護成員及私有成員。
  • 內斂函式一般只會用在函式內容比較簡單的時候,這樣,函式的程式碼會在任何呼叫他的地方展開。行內函數最重要的使用地方是:類的存取函式。

Q10:Qt的垃圾回收機制

Qt是以物件樹的形式來實現對垃圾的收集。所有繼承自QOBJECT類的類,在new的時候就指定了父親,那麼在父親delete的時候,他也被清理delete。

Q11:Qt訊號槽的簡單實現原理?

整個原理是比較複雜的,這裡只做簡單介紹,有興趣童鞋可搜尋細節

  1. 在預編譯時,儲存訊號函式和槽函式的索引為字串,通過巨集定義來實現。
  2. 建立連結,就是講訊號索引字串和槽函式索引字串儲存在map中,建立Key-Value的關係
  3. 當訊號函式觸發後,先去找字串索引,然後再去找map值,然後找到槽函式索引字串,然後再在分支語句中找到槽函式。至此實現,哈哈,這些可以忽悠一下了,不過細節還需準備為好。

Q12:執行緒和程序的區別?

  1. 程序是程式的一次執行;執行緒是程序的執行單元。
  2. 程序間是獨立的,這表現在記憶體空間、上下環境。執行緒執行在程序中。
  3. 一般來講,程序無法突破程序邊界存取其他程序內的儲存空間;而同一程序所產生的執行緒共享記憶體空間。
  4. 同一程序中的兩段程式碼不能同時進行;除非引入多執行緒。