必须 "ask which exact type an object has" 是否总是表示设计不好?

Does having to "ask which exact type an object has" always indicate bad design?

在 SO 的几个地方,声称必须知道对象的确切类型并基于此做出决定(以 if-then-else 方式)指向设计缺陷,例如here

我想知道是否总是这样。在当前的一个小型教育项目(我用来学习 C++)中,我想实现算术结构,即项(例如 (3+4)*x-5)和方程(x=3*y+z)。现在,从结构的角度来看,方程式与项非常相似(特别是它们都可以使用 Shaunting-yard algorithm 进行解析),所以我创建了一个基础 class math_struct 两者 equationterm 派生自:

class math_struct;
class term : public math_struct {...};
class equation : public math_struct {
    void resolve_to(std::string subTerm);
    ...
};

equation 有一个术语 resolve_to 没有的方法(因为方程可以解析为变量,而术语不能),但除此之外它们是相等的。

现在我有一种方法可以从字符串中解析 math_struct

static std::unique_ptr<math_struct> parse_math_struct(std::string formula);

结果 math_struct 可以是项或方程,具体取决于输入字符串的形式。要知道它是哪个,我必须进行 typeid 检查并执行转换以使用 resolve_to 成员函数(如果可用)。

这是设计缺陷吗?我该如何改进它?

我不知道我是否会称它为 "flaw",但我想说设计可以改进。检查类型以查看是否可以调用 resolve_to 的一个潜在问题是,如果出于某种原因,您发现需要从 math_struct 派生的第三个 class,则检查可能会中断。 (有数学背景的人应该知道,想不出原因不代表没有原因。)

一个更强大的选择是向基础 class 添加一个虚函数,一个简单的布尔值 returns true 如果你可以调用 resolve_to.

一个更好的选择可能是考虑如果您正在处理的事情不是一个方程式,您会怎么做。

To know which it is, I have to do a typeid check and perform a cast to use, if available, the resolve_to member function.

如果resolve_to成员函数不可用怎么办?为什么不在基础 class 上有一个虚函数被重写为 terms 做那件事并被重写为调用 resolve_toequations? (或者那是 resolve_to for equations。)

可能在某些情况下,最好的选择是 "ask which exact type an object has",但我不相信就是这样。 (我知道有一个 XML 解析器依赖于这种技术;我还没有分析它是否可以改进。)

您将无法编写通用的 resolve_to。对于不同类型的方程式,您需要一些不同的变体。是的,linear_equation 很简单。 quadratic_equation 并不难。三阶和四阶多项式仍然可以求解,仅此而已 - 可证明。

无论哪种方式 - 您需要一些 resolve_to 变体的事实表明您需要一些 类 从 equation 派生的变体,而您需要知道的是一个对象是否IS-A equation。确切的类型是没有意义的。