我有 300 多个课程。它们在某些方面是相关的。
为简单起见,所有关系均为 1:1。
这是一个示例图。
(In real case, there are around 50 relation-pairs.)
Note:对于某些情况,某些关系可能不存在。
例如,一些hen
s 与任何都不相关food
.
Note2:没有链接=从不,例如每一个egg
与任何无关cage
.
这种关系永远不会被添加/删除/查询。
问题:
如何优雅地保存它们之间的关系?
我的所有 4 个想法(如下)似乎都有缺点。
Here https://stackoverflow.com/questions/18501198/in-c-how-to-best-decouple-2-classes-that-must-maintain-collections-of-referenc是一个相关问题,但具有 1:N 并且只有 1 关系。
我糟糕的解决方案
这些是半伪代码。
版本 1 直接
我的第一个想法是互相添加指针)。
小鸡.h:-
class Egg;
class Food;
class Chick{ Egg* egg; Food* food;}
Hen.h:-
class Egg; class Cage; class Food;
class Hen{ Egg* egg; Cage* cage; Food* food;}
添加/删除关系和查询非常便宜,例如:-
int main(){
Hen* hen; ... Egg* egg=hen->egg;
}
它工作得很好,但随着我的程序的增长,我想将它们解耦。
大致说来,Hen.h
不应包含单词Egg
,反之亦然。
有很多想法,但似乎没有一个很好。
我将展示每个解决方法的简短片段,然后在问题末尾总结优点和缺点。
版本 2 哈希映射
Use std::unordered_map
.
它成为我的程序的瓶颈。 (在发布模式下进行分析)
class Egg{}; class Hen{}; //empty (nice)
.....
int main(){
std::unordered_map<Hen*,Egg*> henToEgg;
std::unordered_map<Egg*,Hen*> eggToHen;
....
Hen* hen; ... Egg* egg=henToEgg[hen];
}
版本 3 Mediator-single
将每个实体的每个关系存储在一个大中介中。
为空插槽浪费大量内存(例如Egg
has henFood_hen
slot).
废物总量=type-of-relation-pair
每个实体中*2*4 字节(如果以 32 位运行)。
class Mediator {
Egg* eggHen_egg=nullptr;
Hen* eggHen_hen=nullptr;
Hen* henFood_hen=nullptr;
Food* henFood_food=nullptr;
//... no of line = relation * 2
};
class Base{public: Mediator m;};
class Egg : public Base{}; //empty (nice)
class Hen : public Base{};
int main(){
Hen* hen; ... Egg* egg=hen->eggHen_egg;
}
版本 4 Mediator-array(与 3 类似)
尝试标准化——灵活性高。
class Mediator {
Base* ptrLeft[5];
Base* ptrRight[5];
};
class Base{public: Mediator m;};
class Egg : public Base{}; //empty (nice)
class Hen : public Base{};
int main(){
enum RELA_X{RELA_HEN_EGG,RELA_HEN_CAGE,RELA_EGG_CHICK, .... };
Hen* hen; ...
Egg* egg=hen->m.ptrRight[RELA_HEN_EGG];
//^ get right of "hen-egg" === get "egg" from "hen"
//^ can be encapsulated for more awesome calling
}
优点缺点
Green (+
) are good. Red (-
) are bad.
Edit:我在用实体组件 http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy对于 60fps 的游戏。
它是一个持久数据库:在游戏的整个生命周期中使用的单个实例。
Edit2:所有关系都是弱关系而不是is-a或强std::unique_ptr
所有权。 (感谢沃尔特)
- A
hen
is in a cage
.
Some hens
不属于任何cage
, 还有一些cages
是空的。
- A
chick
来自 an egg
.
然而,一些chicks
不来自任何egg
(它们只是从天上掉下来的),
还有一些eggs
没有足够幸运成为chick
.
- A
hen
and a chick
正在吃一个(可能相同的)盘子food
.
Some food
盘子刚刚准备好但还没有上桌。
Edit3:为每个对象分配一个整数 id 是一个好主意。
(感谢 Oliv、ahoxha 和 Simone Cifani)
Edit4::不需要提供可编译的代码,只需一个必要的部分/概念就足够了。