【问题标题】:Why is Reference to Base Class ambiguous with :: -operator through derived class?为什么通过派生类使用 :: -operator 对基类的引用不明确?
【发布时间】:2020-04-28 09:01:31
【问题描述】:

所以我想知道为什么菱形问题的以下代码sn-p无法编译。 我知道这个问题通常是通过虚拟继承来解决的,我不是故意使用它的。该代码只是为了展示我关于编译器为何称其为模棱两可的问题: 所以我在 struct Base 中声明了两个成员变量,因为这两个子类(在这种情况下是结构)实际上没有继承,所以我将在每个派生结构中引用 Base 成员。现在我有另一个结构 AllDer,它会在两次知道 id_ 和 name_ 的问题中运行。 但是,当我从 Base 显式定位 id_ 和 name_ 时,我不明白为什么这会模棱两可,因为直接目标变量是通过 ::-operator 指定的。

cout << Der1::Base::id_ << Der1::Base::name_ << '\n';

谁能告诉我,为什么编译器会在这里遇到问题? (请原谅可能错误的技术术语) 编译器错误消息说:“从派生类 'AllDer' 到基类的模糊转换”。在 QT Creator 中使用 MinGW 7.3.0 64 位 C++。

编辑:由于编译器似乎以不同的方式处理此问题,请检查链接的问题。

#include <string>
#include <iostream>
using std::string; using std::cout;

struct Base
{
    int id_;
    string name_; //target members for readAllDer() in AllDer

    void read()
    {
        cout << id_ << ' ' << name_ << '\n';
    }
};


struct Der1 : public  Base
{
    //Der1 has own reference to id_, name_
    void readDer1()
    {
        cout << id_ << name_ << '\n';
    }
};

struct Der2 : public  Base
{
    //Der2 has own reference to id_, name_
    void readDer2()
    {
        cout << id_ << name_ << '\n';
    }
};

//
struct AllDer : public Der1, public Der2
{

    void readAllDer()
    {
        cout << Der1::Base::id_ << Der1::Base::name_ << '\n'; // Why is this ambiguous? 
    }
};

【问题讨论】:

  • 请在问题中包含确切的错误信息
  • 没有Base::,嗯。
  • 在我的机器上工作,你能给我们展示一个用例吗?
  • @Michael OP 也错过了包含错误,但现在我也很好奇你没有得到错误的编译器
  • Microsoft CL (Visual Studio 2019) @idclev463035818

标签: c++


【解决方案1】:

Der1::BaseDer2::Base 是同一个类,AllDer 两次派生自它。当您不是从 Base 而是从 Der1 选择成员时,您的方法将编译:

struct AllDer : public Der1, public Der2
{

    void readAllDer()
    {
        cout << Der1::id_ << Der1::name_ << '\n'; 
    }
};

【讨论】:

  • 这不是虚拟继承。我相信你错了。
  • @Micheal 我不明白你在说什么。 OP 代码中没有虚拟继承,我也没有提到虚拟继承。如果有虚拟继承,那么AllDer 将只包含一个Base 子对象,不会有歧义
  • Der1::BaseDer2::Base 不是同一个对象。它们是同一类型的两个不同对象。您可以通过将Der1::Base::name_ 设置为“A”并将Der2::Base::name_ 设置为“B”来验证它。
  • @Michael Der1::BaseDer2::Base 不是对象而是类型
  • @SörenHepp 因为Der1::Base 不是对象,它是一种类型,并且与Der2::Base 的类型相同。我提出了一个新问题,因为我有疑问(上面的链接)
【解决方案2】:

这是一个经典的菱形问题,即使你说你是通过 scope(::) 指定直接目标变量 这里“Der1”已经有“id_,name_”的副本,而您仍在尝试访问 base 的副本,这对于“AllDer”来说是模棱两可的,因为它来自 Der1 和 Der2 两种方式。

而不是这个:

Der1::Base::id_

试试这个:

Der1::id_ and Der1::name_

希望对你有帮助

【讨论】:

    【解决方案3】:

    你需要像这样从基类虚拟继承 Der1 和 Der2

    struct Der1 : virtual public  Base
    
    
    struct Der2 : virtual public  Base
    

    在这个LINK 中说: 虚拟继承是一种 C++ 技术,可确保只有一个基类成员变量的副本被孙子继承

    【讨论】:

    • OP 很清楚Base 的双重继承,这就是他试图消除_id 成员歧义的原因。
    • 我不明白为什么这个答案是错误的,但感谢您的评论@Yksisarvinen
    • @Yksisarvinen 如果您能解释原因,我将非常感谢
    • 我不是反对它的人,但是 OP 特别不想要虚拟继承(“我知道这个问题通常通过虚拟继承来解决,我没有使用这是故意的。”)。问题是“为什么Der1::Base::_id 是模棱两可的?”
    猜你喜欢
    • 2012-06-05
    • 2012-03-14
    • 2021-12-05
    • 2020-04-25
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-04
    相关资源
    最近更新 更多