【问题标题】:C++ Resolving the diamond problemC++ 解决钻石问题
【发布时间】:2011-07-15 08:21:45
【问题描述】:

难道不能仅通过使用找到的第一个继承声明来解决菱形问题吗?我的意思是,

公共类 A { 公共虚拟 int getInt(); }; 公共类 B:公共 A { 公共 int getInt() {返回 6;} }; 公共类 C:公共 A { 公共 int getInt() {返回 7;} }; 公共类 D:公共 B,公共 C {};

对于class D,由于B 列在第一位,如果调用D::getInt(),我们不能默认(当它不明确时)使用B::getInt() 吗? PATH 环境变量在 UNIX 和其他操作系统中的工作方式;如果在 PATH 变量的不同位置存在两个具有相同名称的事物,则默认情况下应使用第一个位置(除非另有限定)。

编辑:通过“第一个”继承声明找到我的意思是根据简单的从左到右深度优先顺序

编辑#2:刚刚更新了上面的实现,使其更像钻石。

【问题讨论】:

  • 这里没有钻石问题,看起来像普通的旧多重继承
  • 另外,如果有人不小心把订单改成了BAC怎么办?或者在其他类中使用该顺序派生 - 它非常脆弱..
  • 这里的根本问题不是 A 中的任何虚拟成员在 B 或 C 中可能有不同的实现,并且没有办法解决 D 中的这些差异,因为这几乎需要编译器确切地知道你想要完成什么(这会破坏程序员的目的)。
  • 通过任意猜测程序员的意思来解决歧义可能会导致代码的行为与程序员的预期不符。强制程序员明确说明预期的行为会减少出错的空间。

标签: c++ multiple-inheritance diamond-problem


【解决方案1】:

这是一个非常错误的解决方案。想想以下情况会发生什么:

public class A {
    public int getInt() {return 5;}
    public float getFloat() {return 5.0;}
};

public class B {
    public int getInt() {return 6;}
    public float getFloat() {return 6.0;}
};

public class C {
    public int getInt() {return 7;}
    public float getFloat() {return 7.0;}
};

public class D: public A, public B, public C {}

假设一个人希望D::getInt 返回 5,而另一个开发人员希望 D::getFloat 返回 7.0(因此,不同的函数解析为不同的祖先)。第二个开发人员将更改继承顺序,并且根据getInt,所有代码路径中都会出现错误。

【讨论】:

  • 是的,但是如果那个特定的开发组采用“ironclad 编码实践”会怎样:“永远不要更改继承类的顺序!(一旦指定) “?即使始终遵循此规则,是否存在极端情况?
  • 这是不可强制执行的。有一天,在拼命尝试修复分配给他的错误时,开发人员会这样做。而现在,他将在截止日期前夕遇到两个错误。
  • 所以除了人类!= 铁甲(@Nim,确实如此!),默认的从左到右深度优先分辨率应该可以正常工作吗?
  • 不,您可以使用两种或多种方法。其中一些可能需要其他解决顺序
  • 但是从左到右的深度优先分辨率顺序不会明确解决所涉及的方法吗?此外,如果有人特别想要不同的解析顺序,他们难道不能只限定(使用超类名称)要调用的所需方法吗?
【解决方案2】:

不是钻石问题。 C++ 编译器对它的所有语法都是特定的,如果有任何歧义,它总是会抛出错误。

这里你的A::getInt()B::getInt()C::getInt()当你简单地调用d.getInt()时是模棱两可的。

编辑

在您编辑过的问题中,编译器仍然不会从继承中进行评估,因为某些程序员可能确实需要拥有不同的 A==> 第一个通过class B 和第二个通过class C。请注意,所谓的钻石问题是人类特有的问题。对于 C++ 编译器,这只是一种模式。

在 C++ 哲学中,您不仅限于一种范式或模式。您可以选择多重继承。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-07
    • 2017-12-09
    • 2019-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多