【发布时间】:2014-09-12 06:14:22
【问题描述】:
dynamic_cast 是纯粹的邪恶。每个人都知道。只有菜鸟使用 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 的情况下添加实现它的新接口和新类(以及新按钮)。
Object 中的 get_buttons 之类的虚函数对我来说似乎也不好。我的Object 对 GUI、按钮之类的东西一无所知。
像 get_type 这样返回一些枚举的函数也可以解决问题,但我不明白为什么 RTTI 的自我实现替代品应该比原生替代品更好(好吧,它会更快,但它没有在这种情况下没关系)。
【问题讨论】:
-
这是一个很好的问题programmers.stackexchange.com。
-
如果不知道
selected_object是什么,就无法回答这个问题。从表面上看,您根本不需要演员表。 -
我在
selected_object上添加了一些基本信息 -
避免动态转换的一般方法是首先不要丢弃类型信息。您可能会发现访问者模式很有用。对于非常紧密耦合的类,它可以让您完全避免强制转换,否则它可以让您集中强制转换。但首先要认真考虑如何更改您的设计,以避免丢弃所需的信息。例如,考虑两个或多个更受限制且直接有用的集合,而不是所有东西的大集合。
-
“dynamic_cast 是纯粹的邪恶”。好吧,它仍然是检查类是否在运行时实现特定接口的唯一方法。对接口的动态转换并不邪恶...
标签: c++ dynamic-cast