C# property 提供 get/set 存取器,語法如欄位般直觀,且可控制唯讀/唯寫/讀寫。標準 C++ 無原生支援,本文以 純標準 C++ 模板 實現零擴展、可攜帶的 property<> 類別。
obj.Prop = val; (呼叫 set) / val = obj.Prop; (呼叫 get)READ_ONLY、WRITE_ONLY、READ_WRITE 三種模式
#define READ_ONLY 1
#define WRITE_ONLY 2
#define READ_WRITE 3
template
class property {
public:
property() : m_pContainer(nullptr), m_pSet(nullptr), m_pGet(nullptr) {}
// 綁定容器實例 (通常在容器建構函數中呼叫)
void setContainer(Container* pObj) { m_pContainer = pObj; }
// 綁定 set 成員函數指標
void setter(void (Container::*pFunc)(ValueType)) {
if (nPropType == WRITE_ONLY || nPropType == READ_WRITE) m_pSet = pFunc;
else m_pSet = nullptr;
}
// 綁定 get 成員函數指標
void getter(ValueType (Container::*pFunc)()) {
if (nPropType == READ_ONLY || nPropType == READ_WRITE) m_pGet = pFunc;
else m_pGet = nullptr;
}
// 指派運算子 → 呼叫 set
ValueType operator=(const ValueType& val) {
assert(m_pContainer && m_pSet);
(m_pContainer->*m_pSet)(val);
return val;
}
// 型別轉換運算子 → 呼叫 get
operator ValueType() {
assert(m_pContainer && m_pGet);
return (m_pContainer->*m_pGet)();
}
private:
Container* m_pContainer;
void (Container::*m_pSet)(ValueType);
ValueType (Container::*m_pGet)();
};
class PropTest {
public:
PropTest() {
Count.setContainer(this);
Count.setter(&PropTest::SetCount);
Count.getter(&PropTest::GetCount);
}
int GetCount() const { return m_nCount; }
void SetCount(int v) { m_nCount = v; }
// 可讀寫 int 屬性
property Count;
private:
int m_nCount = 0;
};
// 使用
PropTest test;
test.Count = 5; // 呼叫 SetCount(5)
int n = test.Count; // 呼叫 GetCount() → 5
// 唯讀屬性
property ReadOnlyProp;
// test.ReadOnlyProp = 10; // 執行期 assert 失敗
int v = test.ReadOnlyProp; // OK
// 唯寫屬性
property WriteOnlyProp;
test.WriteOnlyProp = 20; // OK
// int v = test.WriteOnlyProp; // 執行期 assert 失敗
| 優點 | 缺點 |
|---|---|
| 語法直觀,符合 C#/VB 習慣 | 每個屬性需一個 property 實例,記憶體微量增加 |
| 編譯期型別安全,執行期模式檢查 | 需在建構函數手動綁定 set/get/container |
| 純標準 C++,跨平台 (GCC/Clang/MSVC) | 無法像 C# 直接在類別內宣告 (需分離綁定步驟) |
| 可擴展支援通知事件、驗證邏輯 | 直接呼叫 Get/Set 函數效能略高 (無運算子解析) |
完整標頭檔 property.h、測試主程式、CMakeLists.txt (跨平台建置驗證)。