C++ C+;中的动态向下投射有什么固有的错误吗+;?

C++ C+;中的动态向下投射有什么固有的错误吗+;?,c++,C++,我听说过好几次,如果你需要动态向下转换,那么设计可能有问题。我将其视为与COMs queryinterface类似的机制,在运行时查询对象以查看它支持哪些接口,然后相应地调用适当的方法 这有什么问题吗?与编程语言的许多其他功能一样,也有适当的用途(COM可能是其中之一),但在大多数情况下,它表明您创建的类型层次结构不够丰富,无法满足您的需要(不提供您需要的所有操作)或者,您正在对不真正相关的类型(因此具有不同的操作集)强制执行继承关系 请注意,COM接口也是如此,其中除了支持哪些接口的基本发布之

我听说过好几次,如果你需要动态向下转换,那么设计可能有问题。我将其视为与COMs queryinterface类似的机制,在运行时查询对象以查看它支持哪些接口,然后相应地调用适当的方法


这有什么问题吗?

与编程语言的许多其他功能一样,也有适当的用途(COM可能是其中之一),但在大多数情况下,它表明您创建的类型层次结构不够丰富,无法满足您的需要(不提供您需要的所有操作)或者,您正在对不真正相关的类型(因此具有不同的操作集)强制执行继承关系

请注意,COM接口也是如此,其中除了支持哪些接口的基本发布之外,对象共享很少甚至没有。但在这种特殊情况下,层次结构中不相关类型的绑定是系统中定义的特定接口的需要。

它本身没有什么问题,有时是适当的,但编写基于对象的动态类型做出决策的代码往往设计得很差。如果你有这样的东西:

void foo(Base const *base) {
  Derived1 const *derived1 = dynamic_cast<Derived1 const *>(base);
  if (derived1) {
    // Do stuff
  }

  Derived2 const *derived2 = dynamic_cast<Derived2 const *>(base);
  if (derived2) {
    // Do stuff
  }
}
void foo(基本常数*Base){
Derived1常量*Derived1=动态施法(基础);
如果(衍生1){
//做事
}
Derived2常量*Derived2=动态施法(基础);
如果(衍生2){
//做事
}
}

您最好将该功能作为一个虚拟函数放到派生类中,并让该语言的内置动态分派负责确定要运行的代码。这样,如果您稍后添加一个
Derived3
,您就不必在代码中查找所有要检查
Derived
Derived2
的位置,也可以添加一个检查
Derived3
。只需在
Derived3
中实现虚拟函数,所有现有的虚拟函数调用都会工作。

@Oli,感谢您的纠正。这就像
goto
:经常被恶意攻击,经常被误用,偶尔是正确的作业工具。非常失望您没有走上
继承
非常错误的双关语路径,这里,我想我是从接口编程的角度来看它的,在这里,你没有一个接口可以做所有的事情,而是有多个接口可以根据需要向一个对象添加功能。示例可能是使集合中的某些对象可序列化,而其他对象不可序列化。所以我想测试可序列化接口。甚至是一组控件,这些控件有一个共同的基类,但它们的功能差异很大,在层次结构中需要额外的功能;在等级制度中,这并不是真正的贬低。在UI控件类的层次结构中,如果要检查特定控件是否支持特定功能,可以为每个功能使用接口(例如,可单击、可调整大小),因为这些也是混入,而不是层次结构的一部分。这和我上面的例子的区别在于,你没有把行为放在基于沮丧的类之外;该行为是在类中实现的,您只需检查是否可以调用它。但是,如果上述方法仅适用于代码中某个特定点层次结构中的一个或两个对象,则它是一个不错的选择。在层次结构的根上添加函数只是为了满足该层次结构中几个项目的一段代码,这是非常可疑的。试图把所有的东西都塞进等级制度的基础会导致一些令人敬畏的代码。