AutoCAD SHX 字型輪廓由圓弧與多段線組成,兩者共享「繪圖」等共同行為。本文展示如何抽象基類、封裝三維點、善用 STL list 建立可擴充的幾何元素類別體系。
struct MYXYZ { double x, y, z; };
class CMyXYZ : public MYXYZ {
public:
CMyXYZ() : x(0), y(0), z(0) {}
CMyXYZ(const MYXYZ& xyz) : x(xyz.x), y(xyz.y), z(xyz.z) {}
CMyXYZ(double x_, double y_, double z_) : x(x_), y(y_), z(z_) {}
virtual ~CMyXYZ() {}
operator MYXYZ() const { return *this; }
const CMyXYZ& operator=(const MYXYZ& xyz) { x=xyz.x; y=xyz.y; z=xyz.z; return *this; }
};
設計考量:
MYXYZ 而非組合,因為「是一個」關係成立,且可直接傳遞給需 MYXYZ* 的 C API。double 儲存座標,預留三維擴充空間。class CMyBase {
protected:
CMyBase() {} // 防止直接實例化
public:
virtual int GetType() = 0; // 回傳 ISARC/ISPOLYLN/ISSHAPE
virtual int Draw(long lDevice) = 0; // lDevice = (long)HDC
virtual ~CMyBase() {}
};
protected 建構子強制衍生類使用。long lDevice 而非 HDC/CDC*,降低平台耦合。#pragma warning(disable:4786 4251 4273)
#include <list>
using namespace std;
typedef list<MYXYZ*> MYPOLYLN; // 存指標:避免拷貝、支援多型、插入刪除 O(1)
class CMyPolyLn : public CMyBase {
public:
CMyPolyLn() { m_PolyLn.clear(); }
virtual int GetType() { return ISPOLYLN; }
virtual int AddPoint(MYXYZ* pxyz) {
m_PolyLn.insert(m_PolyLn.end(), new MYXYZ(*pxyz));
return 0;
}
virtual int Draw(long lDevice) { /* 實作見下篇 */ }
virtual ~CMyPolyLn() {
for (auto p : m_PolyLn) delete p;
m_PolyLn.clear();
}
MYPOLYLN m_PolyLn;
};
list 選擇理由:頂點頻繁尾端新增、中間插入刪除、順序遍歷繪圖,list 符合所有需求且迭代器穩定。
#define ISARC 1
#define ISPOLYLN 2
#define ISSHAPE 3
class CMyArc : public CMyBase {
public:
CMyArc(MYXYZ pc, MYXYZ ps, MYXYZ pe) : m_pc(pc), m_ps(ps), m_pe(pe) {}
CMyArc() {}
virtual int GetType() { return ISARC; }
virtual int Draw(long lDevice); // 實作見下篇
virtual ~CMyArc() {}
MYXYZ m_pc, m_ps, m_pe; // 圓心、起點、終點
};
typedef list<MYXYZ*> MYPOLYLN;
class CMyPolyLn : public CMyBase {
public:
CMyPolyLn() { m_PolyLn.clear(); }
virtual int GetType() { return ISPOLYLN; }
virtual int AddPoint(MYXYZ* pxyz);
virtual int Draw(long lDevice);
virtual ~CMyPolyLn();
MYPOLYLN m_PolyLn;
};
class CShape : public CMyBase { // Composite Pattern: 形狀 = 幾何元素集合
public:
CShape() { m_List.clear(); }
virtual int GetType() { return ISSHAPE; }
virtual int Draw(long lDevice);
virtual ~CShape();
list<CMyBase*> m_List; // 存基類指標,支援異質容器
};
| 模式 | 應用處 | 效益 |
|---|---|---|
| Template Method | CMyBase 定義 Draw 流程骨架 | 統一繪圖介面,衍生類只實作細節 |
| Composite | CShape 含 list<CMyBase*> | 單一/群組物件統一操作,遞迴繪圖 |
| Factory Method (潛在) | 未來可加入 CreateArc/CreatePolyLn | 封裝建構邏輯,支援序列化工廠 |
#pragma warning(disable:4786 4251 4273) 或將 STL 成員移至 private 並提供存取函式。下篇將給出 CMyArc::Draw、CMyPolyLn::Draw、CShape::Draw 完整實作、主程式測試碼,並深入解決跨 DLL new/delete 記憶體管理難題。