【问题标题】:Is there a way to resolve a "final overrider ambiguity" employing a using-declaration?有没有办法使用 using-declaration 来解决“最终覆盖歧义”?
【发布时间】:2019-06-12 22:18:12
【问题描述】:

我正在尝试用虚拟类方法解决一个可怕的菱形问题。

让我们首先考虑一个具有最终虚方法特性的多重继承情况。 由于存在 final 方法,因此无法声明覆盖方法,而必须使用 using 声明来指定子类应使用哪种方法。

class Mother {
public:
    virtual void foo() final {}
};

class Father {
public:
    virtual void foo() {}
};

class Child: public Mother, public Father {
public:
    // void foo() {Mother::foo();} // This clashes with Mother::foo being final
    using Mother::foo;
};

上面的代码按预期工作。

但是,如果我们切换到具有抽象基类的菱形结构,则相同的方法将不再适用。

class GrandParent {
public:
    virtual void foo() = 0;
};

class Mother: virtual public GrandParent{
public:
    virtual void foo() override final {};
};

class Father: virtual public GrandParent{
public:
    virtual void foo() override {};
};

class Child: public Mother, public Father {
    using Mother::foo;
};

编译以上代码会报错:no unique final overrider for ‘virtual void GrandParent::foo()’ in ‘Child’

关于如何解决这个问题的任何想法?

【问题讨论】:

  • 这可能会有所帮助;如果子类的虚函数声明与基类声明不匹配,override 用于生成编译器错误。 final 关键字通常用于表示您不能从这样的类派生。

标签: c++ abstract-class multiple-inheritance using virtual-functions


【解决方案1】:

这是告诉您设计错误的语言。它是。继承反映了“is-a”关系。不是“有”。

解决方案是使用组合而不是继承。我会举一个例子,但完全不清楚你真正打算完成什么,也想不出任何合理的例子。

【讨论】:

  • 关于这个主题的补充阅读:What is an example of the Liskov Substitution Principle?
  • 我想要一个通用的基类(在本例中为 GrandParent),它用于定义一个抽象接口(除了 foo 之外还有更多的方法)。然后使用子类(如母亲和父亲)根据特定假设提供所述接口的一些(但不是全部)实现。其中一些假设非常严格,以至于部分实现不应更改(最终)。最后一个孩子应该结合实现。
  • @cxkoda 这是您提出的解决方案,硬塞到您认为适用的概念中,而不是您尝试解决的实际问题,而不假设解决方案是什么样的。
  • @rubenvb 是的,你当然是对的,因为我正试图将我的问题融入一个可能不太合适的结构中。但是,我不明白为什么第一个代码有效而第二个代码无效。
  • @cxkoda 2 件事 1) 虚拟继承处理公共基类GrandParent。它不处理父类之间的差异。 2) class.virtual 声明 如果基类子对象的虚拟成员函数具有多个最终覆盖程序,则程序格式错误。 这就是陷阱。一旦你必须消除父母的foos 之间的歧义,你就必须打破这个规则。
猜你喜欢
  • 2022-12-03
  • 1970-01-01
  • 2013-09-11
  • 2015-04-18
  • 2010-10-19
  • 2018-10-05
  • 1970-01-01
  • 1970-01-01
  • 2012-09-03
相关资源
最近更新 更多