C++ Primer 核心知識點整理,涵蓋類設計、繼承、多態、模板、異常處理、智能指針、命名空間等 88 條精華要點,適合面試複習與工程參考。
類設計基礎 (1-12)
- 類內定義函數隱式
inline,需在頭文件定義以便編譯器展開
assert 僅用於內部邏輯檢查,發布版自動禁用
- 異常處理優於錯誤碼,保證棧展開釋放資源
- 流對象不可拷貝,容器存儲/參數傳遞需用引用/指針
- 重用文件流需
clear() 重置狀態後再 open()
- 前向聲明後類為不完全類型,僅能定義指針/引用、聲明函數
- const 成員函數只能返回
const 引用/指針
- 全局變量訪問用
::var 區分同名參數
- const/引用/無預設構造的成員必須用初始化列表
- 初始化列表順序應與成員聲明順序一致
- 若定義其他構造函數,幾乎總應提供預設構造函數
- 友元非成員、不受訪問控制,通常集中放在類首/尾
靜態成員與拷貝控制 (13-22)
static 成員函數無 this,不可 const/virtual
static 數據成員必須在類外定義
- 拷貝構造用於容器元素初始化 (先預設構造臨時值,再拷貝)
- 禁止拷貝:聲明
private 拷貝構造/賦值,不定義 → 鏈接錯誤
- 不可拷貝類對象只能傳引用、不可放入標準容器
- 容器銷毀按逆序:先
size()-1 後 0
- 三法則:需析構函數 ⇒ 需拷貝構造 + 賦值操作符
- 合成析構不刪除指針成員指向對象
- 析構函數無參數、無返回值、不可重載、唯一
- 自定義析構後合成析構仍執行 (先自定義後合成)
- 指針成員三種管理策略:普通指針、智能指針 (共享)、值語義 (獨有)
運算符重載與轉換 (23-33)
- 不可重載:
:: .* . ?:
- 重載運算符至少一個類/枚舉類型操作數
- 優先級/結合性/操作數數目不可變,
operator() 除外禁用預設參數
- 成員運算符隱含
this 為第一操作數,算術/關係運算符宜非成員
- 勿重載
, & && || (失去內置短路/序列點語義)
- 含義不明時用命名函數替代運算符
- 容器鍵類型應定義
== 和 < (算法依賴)
- 下標運算符通常定義 const/非 const 兩版本
- 類型轉換函數:成員、無返回類型、無參數、通常
const
- 類類型轉換不可串聯 (一步到位)
繼承與多態 (34-50)
- 派生類只能通過派生對象訪問基類
protected 成員
- 派生類調用基類虛函數必須加作用域
Base::func(),否則無限遞歸
private 繼承可用 using Base::mem 暴露基類成員
class 預設 private 繼承,struct 預設 public
- 友元關係不可繼承
- 基類
static 成員整個繼承體系僅一份
- 構造函數只初始化直接基類,不直接初始化基類成員
- 析構函數不負責基類成員,編譯器自動調用基類析構
- 繼承體系根類必須定義虛析構函數
- 只有析構函數可
virtual,構造/賦值不可
- 構造/析構中調用虛函數 → 靜態綁定 (當前類版本)
- 派生類作用域嵌套在基類中,同名成員遮蔽基類 (含重載)
- 使用
using Base::func 引入基類所有重載版本
- 虛函數原型在基類/派生類必須完全一致
- 同名函數遮蔽虛函數 → 需用基類指針/引用調用基類版本
- 派生對象賦值給基類對象會「切片」,容器存基類對象失去多態
模板與泛型編程 (51-60)
- 運行時多態 (OOP) vs 編譯時多態 (模板/參數化)
- 模板參數名不可在模板內重用
typename 前綴告訴編譯器依賴名是類型
- 陣列參數可聲明為引用
T (&)[N],保留大小資訊
- 顯式模板實參按順序匹配形參
- 包含編譯模型:編譯器必須看到模板定義 (頭文件實作)
- 非類型模板實參必須是編譯期常量表達式
- 特化/偏特化可有完全不同的成員集合
- 函數模板可重載 (同名不同參數)、可與普通函數同名
異常處理與資源管理 (61-75)
- 異常對象由拷貝創建,類型必須可拷貝
- 拋出指針通常是壞主意 (需保證指向對象存活)
- 棧展開:釋放局部對象、調用類類型析構函數
- 析構函數拋出異常 →
terminate() → abort()
- 構造函數拋出異常需確保已構造成員正確清理
- 無匹配
catch → terminate()
catch 類型必須完整定義,前向聲明無效
- 捕獲繼承體系異常宜用引用參數
catch(...) 必須最後,否則後續 catch 永不匹配
- 構造函數處理初始化列表異常 → 函數 try 塊
- 異常安全 = RAII:構造獲取資源、析構釋放資源
auto_ptr 缺陷:拷貝轉移所有權、不可放容器、不可管理陣列
auto_ptr 不可直接賦值地址,需 reset()/構造
異常規格與命名空間 (76-88)
- 無異常規格 = 可拋出任意異常
- 編譯器不驗證異常規格,運行時違規 →
unexpected() → terminate()
- 異常規格實用場景:
noexcept 保證不拋出 (優化/契約)
- 派生類虛函數異常規格不得比基類寬鬆
- 函數指針賦值:源異常規格不得比目標寬鬆
- 命名空間可定義在全局/命名空間中,不可在函數/類中
- 命名空間可分多部分定義,累積合併
- 未命名命名空間僅限單文件,替代
static 文件局部
- 頭文件含未命名命名空間 → 每個包含文件產生不同實體
- ADL (參數相關查找):同名空間的函數/運算符在類類型實參時可見
- 模板特化必須在原模板命名空間中定義
- 虛繼承:最底層派生類構造虛基類,虛基類優於非虛基類構造
sort 預設 less 遞增序
- 模板函數 = 函數模板的具體實例化