類 B 和 C 繼承自基類 A。C 需要調用 B 的方法,但不想直接持有 B 的指針(耦合、生命週期管理困難)。解決方案:在基類 A 中維護一個靜態註冊表,所有子類實例構造時自動註冊,析構時注銷。C 通過遍歷註冊表查找 B 類型實例並調用。
ChildrenNode Children[N],存儲 void* 指針 和 類型枚舉addChildren(void*, NodeType)、delChildren(index)、getChildren(index)addChildren(this, T_B),析構時 delChildren(index)getChildren() 遍歷,根據類型 static_cast<B*>(ptr) 調用 B 方法
// A.h
#ifndef A_H
#define A_H
enum NodeType { T_A=0, T_B=1, T_C=2, T_Count };
struct ChildrenNode { void* p; int type; };
class A {
public:
A(); ~A();
static int addChildren(void* child, NodeType type);
static void delChildren(int index);
static const ChildrenNode* getChildren(int index);
static const int N = 10;
private:
static ChildrenNode Children[N];
};
#endif
// A.cpp
#include "A.h"
ChildrenNode A::Children[N] = {};
A::A() {} A::~A() {}
int A::addChildren(void* child, NodeType type) {
if (!child || type >= T_Count) return -1;
for (int i=0;i=0 && index=0&&index
B::B() { sum = addChildren(this, T_B); }
B::~B() { delChildren(sum); }
void B::PrintSum() { printf("B: %d\n", sum); }
// C.h
#include "A.h"
class C : public A {
public:
C(); ~C();
void PrintAllBsum();
};
// C.cpp
#include "C.h"
#include "B.h"
C::C() {} C::~C() {}
void C::PrintAllBsum() {
for (int i=0;ip && node->type == T_B) {
static_cast(node->p)->PrintSum();
}
}
}
// main.cpp
#include "B.h"
#include "C.h"
#include
int main() {
C c;
B* bs[10];
for (int i=0;i<10;++i) {
bs[i] = new B();
sleep(1);
c.PrintAllBsum(); // 動態發現並調用所有 B 實例
}
for (int i=0;i<10;++i) delete bs[i];
return 0;
}
B: 0 B: 0 B: 1 B: 0 B: 1 B: 2 ...
每次新建 B,C 都能立即發現並調用其方法。
| 優點 | 缺點 |
|---|---|
| 解耦:C 不依賴 B 具體定義,僅依賴基類註冊機制 | 靜態數組容量固定(N=10),需預估最大實例數 |
| 動態發現:運行時創建/銷毀 B 實例自動生效 | 類型轉換用 static_cast,需確保類型匹配(可用 dynamic_cast 配合 RTTI) |
| 無需傳遞指針:適合插件架構、模塊化系統 | 基類膨脹:註冊邏輯污染基類職責 |