在我的模拟中,我可以通过三种方式感知不同的对象:可以看到和/或听到和/或闻到对象。例如,可以看到,听到和闻到动物。可以看到并闻到一块肉在地面上,但闻不到,只能看到墙。然后,我有收集此信息的不同传感器-EyeSensorEarSensorNoseSensor

之前状态:简短版本gist.github.com link

在开始实现NoseSensor之前,我在一个类中具有所有对象都继承的所有三种功能-CanBeSensed,因为尽管类不同,但它们都需要相同的getDistanceMethod(),并且如果对象实现了任何CanBeSensed功能,则需要SenseMask-标记是否可以听到/看到对象/ smelled,我不想使用虚拟继承。我牺牲了在此类中使用数据成员来获取气味,声音和EyeInfo,因为只能看到的对象不需要气味/声音信息。

然后将对象注册到相应的传感器中。

现在,我注意到气味传感器和声音传感器是相同的,只是循环中的一行不同-一个在getSound()对象上调用float float getSmell(),另一个调用CanBeSensed*。当我创建这两个传感器之一时,我知道它需要调用什么,但是我不知道如何在没有条件的情况下选择该行,它处于紧密循环和虚函数内。

因此,我决定使用getDistanceMethod()为基类使用虚拟继承为这3个功能创建单个基类。

但是现在由于这种方法,我不得不将我的SensorBase类设为模板类
virtual void sense(std::unordered_map<IdInt, CanBeSensed*>& objectsToSense) = 0;
,这意味着我还需要使SensorySubSystem类(管理范围内的传感器和对象)也成为模板。这意味着我的所有子系统(例如VisionSubSystem,HearingSubSystem和SmellSubSystem)都从模板类继承,这打破了我的SensorySystem类,该类通过指向SensorySubSystemstd::vector<SensorySubSystem*> subSystems;的指针的 vector 来管理所有SensorySubSystems。

请问您是否可以提出一些解决方案,以了解如何重组此结构或如何使编译器在编译时确定(或至少每个调用一次确定//每个对象创建一次确定)在Hearing / Smell Sensor中调用哪种方法。

最佳答案

看看您的原始设计,我有几点评论:

  • hierarchy.cpp中的类设计对我来说还不错。
  • 除非距离是特定于感官信息的东西,否则getDistance()看起来并不像属于此类的方法。可以将其移动到Vec2d类或辅助函数中(calculatePositon(vec2d,vec2d))。我看不到,为什么getDistance()是虚拟的,如果它执行的操作与计算给定位置和对象位置之间的距离不同,则应将其重命名。
  • 类CanBeSensed听起来更像是一个属性,应该将其重命名为例如。 SensableObject。

  • 关于您的新方法:
    继承应主要用于表达概念(关系),而不是共享代码。如果要重用算法,请考虑编写算法类或函数(偏重继承而不是继承)。

    总而言之,我建议如上所述使您的原始类(class)设计清理干净一点。您可以将虚拟函数canBeSmelled / canBeHeard / canBeSeen添加到CanBeSensed。
    或者,您可以创建一个类层次结构:
  • 类Object {getPosition();
  • 类ObjectWithSmell:虚拟对象
  • 类ObjectWithSound:虚拟对象
  • ...

  • 但是随后您将不得不处理虚拟继承而没有任何明显的好处。
    共享的计算代码可以进入算法类或函数。

    09-25 18:13