序言:这个问题比较高级,直接回答问题不觉得有压力。例如,如果您相信更好的设计方法,请告诉我。
我们正在制作一个易于修改的软件,使用ECS设计模式并遵循开闭原则。这产生了以下要求:
这一切都可以完成:最小可重现示例和
您可以自己测试代码是否有效。
但是,我们有一个很大的设计问题:(如果我们高于第二位,则不会崩溃,这是一个最小的示例)
ExampleObject->FeatureList |= (1 << 0); // Spawn Feature1
ExampleObject->FeatureList |= (1 << 1); // Spawn Feature2
ExampleObject->FeatureList |= (1 << 2); // Spawn Feature3
如您所见,我们有硬编码的特征值。这打破了我们的第三个要求。这些硬编码值也基于编译顺序,这并不理想。
这可以通过搜索算法来解决,以从
std::unordered_map<int, std::string> Map;
中查找整数。示例代码如下所示:
ExampleObject->FeatureList |= (1 << FeatureRegistry::GetInstance().GetFeatureValue("Feature1"));
ExampleObject->FeatureList |= (1 << FeatureRegistry::GetInstance().GetFeatureValue("Feature2"));
ExampleObject->FeatureList |= (1 << FeatureRegistry::GetInstance().GetFeatureValue("Feature3"));
但这需要使用硬编码字符串:如果某个功能的名称要更改或完全删除,则没有快速方法可以在代码库中替换该名称或禁用功能生成。 (我们必须依赖编译器错误,这并不理想)
有一种解决方案可以处理名称到整数而无需对值进行硬编码:枚举器。我们甚至可以在大多数 IDE 上使用自动完成功能来明确我们可以生成什么和不能生成什么,以及轻松替换名称和将值设置为 null!
所以我们需要一个枚举器,它为每个注册的功能都有一个定义的值。
这非常简单:在
REGISTER_FEATURE
宏中添加一个枚举器,并且……这里没有明确的前进方向。没有动态分配枚举器或在多个文件之间共享的宏内声明枚举器的信息:有不透明和匿名的枚举器声明,但尚不清楚如何利用它们。
如何在宏中声明枚举值?