gpt4 book ai didi

c++ - 我的菱形继承(钻石问题)编译器错误无法解决?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:20:51 26 4
gpt4 key购买 nike

结构
我创建了菱形继承(钻石问题)问题。看起来像这样
inheritance diagram
我以为我对虚拟继承了解得很好,但是现在我觉得我对它有点误解了。

我的理解是,虚拟继承告诉编译器忽略任何成员数据或函数,这些成员数据或函数由于菱形继承模式而以相同的名称出现两次,因此派生类中将仅包含“非虚拟”继承的组件。

  • 但是,我现在认为对编译器如何实现继承的这种理解是错误的。

  • 我的继承层次结构中有2个菱形继承模式。它们使用随附的注释进行标记。
    我还添加了一些注释,以显示尝试将 virtual放在哪里以解决编译器错误,但是导致了另一个编译器错误。该注释简要描述了问题所在。 (如果您有兴趣,请参阅此问题的最后一节)
    使用情况
    预期用途是创建了 std::list<GUIObject*>。所有gui对象都应该能够使用 DrawProcessEvent。并非所有的gui对象都将包含 SingleLineBuffer内包含的容器。 BufferFileBuffer继承自 SingleLineBuffer来更改 SingleLineBuffer内部的容器的行为。 ( FileBuffer实际上仅添加了新文件IO功能。)
    可以创建其中一个缓冲区的实例,但是我不在所使用的上下文中。
    不能创建任何抽象 GUI*类的实例。考虑到这一点,在 GUIMultilineTextEntry下可能应该有一个继承自 FileBuffer的附加抽象基类。
    用户可以创建实例的实际对象是 LabelInputboxTextbox。我打算在将来添加更多内容,例如多行标签。这可能必须继承自从 BufferGUITextObject继承的基类。
    这种继承结构很快变得非常复杂。我在编写过程中一直按照代码指示我执行的操作来编写它。例如,我写了一个Textbox类,然后说:“Textbox中的容器与Label中的容器本质上是相同的,因此它们应该从一个公共(public)对象继承”。区别在于,文本框具有文件IO,要求附加的继承步骤,并且文本框可以在容器中包含换行符,因此此处也要求附加的继承步骤。
    问题
  • 是否可以解决此继承问题?
  • 哪些类应该实际上从哪些其他类继承。

  • 我的尝试
  • 没有虚拟继承

  • 编译器错误:(的多个版本)
    error: request for member ‘Size’ is ambiguous
    status_text << "Save: " << static_cast<Textbox*>(current_window._guiobject_map_.at("textbox"))->GetFilename() << ", " << static_cast<Textbox*>(current_window._guiobject_map_.at("textbox"))->Size() << " bytes";
    SizeSingleLineBuffer中定义。这是一个非虚拟函数,因为该容器仅存在于 SingleLineBuffer中,因此 Size被编写为 BufferFileBuffer均能正常工作。
  • 打破菱形1:将virtual放在GUITextObjectGUITextEntry之间,以防止Size在Buffer中被覆盖之前“通过GUITextObject下拉”。 (蓝色标记)

  • 编译器错误(1):
    error: no matching function for call to ‘GUITextObject::GUITextObject()’
    我可以通过从 GUIMultilineTextEntry调用所需的构造函数来解决此问题。我不明白为什么需要这样做。 ( 第二个问题)修复如下所示:
    GUIMultilineTextEntry(const FontTextureManager& ftm, const int width, const int height)
    : GUITextEntry(ftm, width, height)
    , GUITextObject(ftm, width, height) // also call the constructor for the class which was inherited virtual in the previous step
    { ...
    InputboxTextbox中也需要相同的修复程序。
    但是,这会导致进一步的错误
    error: cannot convert from pointer to base class ‘GUIObject’ to pointer to derived class ‘Textbox’ via virtual base ‘GUITextObject’
    static_cast<Textbox*>(current_window._guiobject_map_.at("textbox"))->SetFilename(filename);
    我相信可以通过使用 dynamic_cast而不是 static_cast来解决此问题,但是我不确定这是一个好主意,因为我听说动态转换会大大降低代码速度。
  • 破坏钻石1,第二次尝试:

  • 我再次尝试通过在 BufferSingleLineBuffer之间继承来解决此问题。 (请参阅红点)但是,当我这样做时,编译器错误更改为
    error: no unique final overrider for ‘virtual void SingleLineBuffer::SetText(const string&)’ in ‘Textbox’
    我的猜测是,这相当于编译器告诉我“您通过继承重写了Buffer中的某些函数,但实际上是继承的,并且通过非虚拟继承在派生类中也存在被重写的函数,因此我不知道哪个人该当总统”-但这确实是一个猜测。
  • 我尝试了类似的操作来破坏Diamond 2,但是遇到了类似的编译器错误。

  • 由于这是一个很长的问题,因此在此我不会列出该尝试的所有详细信息。

    最佳答案

    名义问题的答案是no。 (通常,MCVE会出现在问题中,但我想这里确实是答案。)至于详细问题:

  • 如果继承直接来自公共(public)祖先(“钻石的顶端”),而您只希望在完整对象中复制一个拷贝,则继承必须为virtual。 (因此,在这里,仅需要计算会聚的箭头,就需要4 virtual。)
  • 您需要在每个concrete类中调用每个虚拟基址的构造函数,因为most-derived class直接对其进行初始化。
  • 实际上,您不能从虚拟基(或通过它说)使用static_cast,因为实例之间的类布局有所不同(因为其他基类有所不同)。但是,每个GUI操作花费一个dynamic_cast的成本肯定是无法估量的。
  • 您的“唯一最终替代者”错误分析可能是正确的,但答案是更多的母牛皮virtual
  • 关于c++ - 我的菱形继承(钻石问题)编译器错误无法解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50655772/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com