假设我想要一个可以使用基类/接口list<Animal*>
管理不同动物的程序。动物可以有特定的行为(Fly / Climb / ThrowPoo)。目标是迭代Animal*
并使用他们的特定行为对他们执行某些操作。
首先想到的是使用dynamic_cast
或static_cast
+ typeid
来投射Animal
。但是这种方法难以维护,如果我有更多的对象可以迭代,那么这种方法会变得很慢。
经过一番研究后,我发现以下方法可以避免使用RTTI并使用虚函数调用:
bool canFly()
类中的虚拟方法。在我看来,这两种方法都有自己的缺陷。第一个污染动物类和它的派生类有很多丰富的代码/实用程序,如果你想避免特定的函数调用,你需要一些方法,如{{1}}(如果函数保证一些行为随叫随到)。我非常喜欢第二种方法,但它远不像前一种那样容易阅读和理解。
您能详细说明一下铸造(RTTI),虚拟功能和动态调度模式的优缺点以及何时正确使用它们?此外,如果我错过任何方法或策略,请在比较中包括它们。
答案 0 :(得分:1)
我认为当你考虑dynamic_cast
时,你会想到makeYourSound(Animal* a)
函数由200个if...else if
块组成,每个块都测试和处理特定类型动物是的,那是缓慢且不可维护的。不要这样做。
dynamic_cast
有什么好处,实际上是可选接口。某些动物可以做的特别的事情,但不是其他动物。 if(Eagle* e = dynamic_cast<Eagle*>(a))
是代码气味,是一种糟糕的气味。 if(IFly* f = dynamic_cast<IFly*>(a))
闻起来更少。它避免了代码重复,它避免了使用无意义的方法污染基类并围绕如何处理非飞行动物进行跳舞,并且它在您的代码中更准确地描述您正在尝试做什么。 / p>
基于虚函数的多态性的优点是对象完全负责,这对OO纯粹主义者有很大的吸引力。但在某些情况下,作为一个实用的程序员,你不会希望控制对象,只是告诉你的代码更多关于它自己,以便它可以正确处理。更加细致入微的指南,如OCP,可以更广泛地应用,它们不排除dynamic_cast
,只是不分青红皂白地使用它。