首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

C++ 基礎深度講解:面向物件程式設計思想(二)——封裝的真相與包裝類模式

     編輯:C++ 入門

接續上篇,本文深入剖析「封裝」的真實含義,揭露 Getter/Setter 反模式,確立包裝類設計模式,闡述面向物件架構的核心原則。

面向物件編程思想回顧

  • **設計程式 = 編寫問題領域的論述(論調)**。
  • 論調由「名詞性概念」(資源類型)與「動詞性概念」(操作)構成。
  • **物件 = 名詞性概念的實例**(具狀態/屬性/功能)。
  • **動詞性概念**可映射為無狀態類(STL 函數物件)或全域函數,**切勿為演算法便利強行加入成員函數**(如給汽車加 SpinInPlace()),破壞架構清晰度。

封裝 ≠ 資料隱藏 + Getter/Setter

教科書典型錯誤範例:


class Person {
private: char m_Name[20]; unsigned long m_Age; bool m_Sex;
public:  const char* GetName() const; void SetName(const char*);
         unsigned long GetAge() const; void SetAge(unsigned long);
         bool GetSex() const; void SetSex(bool);
};

三大謬誤:

  1. 有門無鎖: Getter/Setter 完全暴露內部結構,零封裝價值。
  2. 無法隱藏佈局: 編譯器生成代碼**必須知內存佈局**(大小、偏移)。使用者可用 #define private public、強制轉型、相容結構體繞過 private。
  3. 語義錯位: Person 若為資料庫緩衝區,本質是「箱子」,不應有 Get/Set;若為領域模型,行為應為 ChangeName、Promote 等業務動作。

真正的封裝:操作的封裝 → 包裝類

MFC CFile 封裝「檔案操作」而非「檔案資料」:


class CFile {
    HANDLE m_hFile;  // 被封裝資源句柄
public:
    void Open(...);   // 被動功能:被開啟
    void Close();     // 被動功能:被關閉
    void Read(...);   // 被動功能:被讀取
    void Write(...);  // 被動功能:被寫入
};

封裝定義: 將**對某資源的一組操作**集合視為一種新資源,映射為**包裝類**。

  • 包裝類映射「動詞性概念」(操作),非「名詞性概念」(實體)。
  • 包裝物件持有被包裝資源引用(m_hFile),操作時透過引用轉發。
  • 包裝物件**獨立於**被包裝資源:CFile f; 初始無效,Open 綁定,Close 解綁,物件存活。
  • 優點:將多「動詞性概念」合併為一「名詞性概念」,簡化架構,趨向純面向物件。

封裝 vs 繼承:老虎吃兔子

  • Tiger::Eat(Rabbit&):老虎主動功能,涉及兩資源。
  • RabbitWrapper::BeEaten():兔子包裝類封裝「被吃」操作,單一資源。
  • 兩者語義不同、層次不同,**可共存**,視領域模型而定。

面向物件架構鐵律

設計類時,若映射領域概念,邊界以領域為準,勿因演算法需求添加錯誤成員。

  • 名詞性概念 → 類,屬性/狀態 → 成員變數,功能 → 成員函數。
  • 動詞性概念 → 傾向全域函數(或無狀態函數物件),保持架構清晰。
  • 演算法中操作領域類物件時,**嚴禁將複雜操作塞入該類**作為成員函數。

理解封裝本質,避免 Getter/Setter 濫用,掌握包裝類模式,才能設計出高內聚、低耦合、語義豐富的 C++ 系統。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved