面向對象編程(OOP)的本質是定義問題域專屬的數據類型。類不僅封裝數據(屬性)與操作(方法),更建立了現實世界實體與計算模型的映射:
public 成員函數定義「能做什麼」,隱藏「怎麼做」。private 保護不變量,protected 供派生類擴展。派生類對象內存佈局:基類部分 + 派生類自有成員。基類子對象由基類構造函數初始化,派生類構造函數通過成員初始化列表指定調用哪個基類構造函數:
class CBox { // 基類:通用箱子
public:
double m_Length, m_Width, m_Height;
explicit CBox(double lv=1.0, double wv=1.0, double hv=1.0)
: m_Length(lv), m_Width(wv), m_Height(hv) {}
};
class CCandyBox : private CBox { // 派生類:糖果盒
public:
char* m_Contents;
explicit CCandyBox(const char* str = "Candy")
: CBox(), // 顯式調用基類默認構造
m_Contents(new char[strlen(str)+1]) {
strcpy_s(m_Contents, strlen(str)+1, str);
}
// 禁用拷貝,避免淺拷貝雙重釋放
CCandyBox(const CCandyBox&) = delete;
CCandyBox& operator=(const CCandyBox&) = delete;
~CCandyBox() { delete[] m_Contents; }
};
| 繼承方式 | 基類 public 成員在派生類中 | 基類 protected 成員在派生類中 | 基類 private 成員 | 語義 |
|---|---|---|---|---|
public | public | protected | 不可訪問 | is-a 關係,對外暴露基類接口 |
protected | protected | protected | 不可訪問 | 僅供進一步派生類使用 |
private (默認) | private | private | 不可訪問 | implemented-in-terms-of,純實現復用 |
鐵律:基類 private 成員在派生類中永遠不可訪問,無論繼承方式。訪問級別只能收窄,不能放寬。
virtual ~Base(),否則派生類析構不被調用導致資源洩漏。
class CCandyBox : private CBox {
public:
// 派生類拷貝構造:先調用基類拷貝構造,再深拷貝自有資源
CCandyBox(const CCandyBox& other)
: CBox(other), // 基類部分拷貝
m_Contents(new char[strlen(other.m_Contents)+1]) {
strcpy_s(m_Contents, strlen(other.m_Contents)+1, other.m_Contents);
}
// 拷貝賦值同理:檢查自賦值、釋放舊資源、基類賦值、深拷貝新資源
CCandyBox& operator=(const CCandyBox& other) {
if (this != &other) {
CBox::operator=(other); // 基類賦值
delete[] m_Contents;
m_Contents = new char[strlen(other.m_Contents)+1];
strcpy_s(m_Contents, strlen(other.m_Contents)+1, other.m_Contents);
}
return *this;
}
};
final (C++11)
class CBox final { /* ... */ }; // 編譯器禁止 class Derived : CBox
// final 是上下文關鍵字,非保留字,可作變量名
private/protected 成員。operator<< 需訪問私有數據)、工廠類創建私有構造對象、單元測試框架訪問內部狀態。
// CBottle.h
class CCarton; // 前向聲明
class CBottle {
friend CCarton::CCarton(const CBottle&); // 友元聲明需完整函數簽名
double m_Height, m_d;
public:
CBottle(double h, double d) : m_Height(h), m_d(d) {}
};
// CCarton.h
class CBottle; // 前向聲明
class CCarton {
double m_Height, m_Width, m_Length;
public:
CCarton(const CBottle&); // 參數為引用,僅需前向聲明
};
// CCarton.cpp
#include "CCarton.h"
#include "CBottle.h" // 實現處需完整定義
CCarton::CCarton(const CBottle& b)
: m_Height(b.m_Height), m_Length(4.0*b.m_d), m_Width(3.0*b.m_d) {}
規則:頭文件中僅用到指針/引用/返回類型 → 前向聲明;源文件實現需完整定義 → #include。不可用於:定義值類型成員、基類列表、sizeof、實例化模板。
public 繼承必須滿足里氏替換原則。virtual,無例外。public 繼承 + 虛函數實現多態,private/protected 繼承僅用於實現復用(策略模式可用組合替代)。final 封鎖不應擴展的類,override 強制檢查覆寫正確性。