dynamic_cast是纯粹的邪恶。大家都知道。只有noobs使用dynamic_cast。 :)
这是我读到的关于dynamic_cast的内容。 stackoverflow上的许多主题都说"在这种情况下使用虚函数"。
我有一些反映对象功能的界面。让我们说:
class IRotatable
{
virtual void set_absolute_angle(float radians) =0;
virtual void rotate_by(float radians) =0;
};
class IMovable
{
virtual void set_position(Position) =0;
};
和一组可以实现它们的类的基础:
class Object
{
virtual ~Object() {}
};
在GUI图层中,我想启用/禁用或显示/隐藏按钮,具体取决于用户选择的对象实现的功能:
Object *selected_object;
我会这样做(简化):
button_that_rotates.enabled = (dynamic_cast<IRotatable*>(selected_object) != nullptr);
(...)
void execute_rotation(float angle)
{
if(auto rotatable = dynamic_cast<IRotatable*>(selected_object))
{
rotatable->rotate_by(angle);
}
}
但正如其他(更有经验的人)所说,这是设计糟糕的明显证据。
在这种情况下,什么是好的设计?
不,我在Object
中不想要一堆虚拟功能。我希望能够在不触及Object
的情况下添加新界面和实现它的新类(以及新按钮)。
get_buttons
中Object
之类的虚拟函数对我来说似乎并不好。我的Object
完全不了解GUI,按钮等等。
像get_type
这样的函数返回一些枚举也可以解决问题,但我不明白为什么自我实现的RTTI替代品应该比原生代码更好(好吧,它会更快) ,但在这种情况下并不重要。)
答案 0 :(得分:1)
你已经敲了敲头:你正试图从“不透明的”对象*类型中获取类型信息。使用dynamic_cast只是一个黑客到达那里。可以说你的问题实际上是C ++没有你想要的东西:良好的类型信息。但是这里有一些想法。
首先,如果你要做很多这类事情,你可能会发现你实际上已经脱离了典型的继承,你的程序可能更适合基于组件的设计模式,这在视频游戏。在那里,你经常在根处有一个不透明的GameObject,想知道它有什么“组件”。 Unity做了这样的事情,他们有很好的编辑器窗口,基于附加到GameObject的组件;但是C#也有很好的类型信息。
其次,可能的其他部分可能知道对象的具体类型,并且可以帮助构建您的可视化显示,从而导致Object *不再成为瓶颈。
第三,如果你选择了类似你正在讨论的选项,我认为你会发现某种类型的id与使用dynamic_cast更有帮助,因为你可以构建表格来查看可以说,视觉建设者。
另外,您想知道为什么自动卷型信息与RTTI?如果您非常关注性能,RTTI适用于所有类型,这意味着一切都可能受到打击;自动滚动选项允许选择加入(以复杂性为代价)。此外,如果您正在编写通过源等引入的库,则无需将其推送到其他人