多重继承与类相同的变量名

问题描述 投票:1回答:3

我不小心碰到具有在多重继承使用类的同名成员变量的问题。我的基本想法是,成员变量是简单的“合并”,即多发生宣言。编译器没有告诉我甚至警告,请参见下面的MWE。据我所知,这是一个坏主意,有相同名称的变量,所以我认为这至少是不明确的提及他们在我的方式;所以我预计将有至少一个警告或可能的错误。

1)为什么编译器不会写出至少一个警告?

2)如何这些变量的处理在内部解决了吗? (我想喜欢HW ::我和其他::我使用别名,但它们与SW1 ::我和SW2 ::我?)

#include <iostream>
struct Other { int I;};
struct HW { int I;};
struct SW1 : Other, HW { int I;};
struct SW2 : HW, Other { int I;};
struct D : SW1 { };
struct E : SW2 { };

int main()
{
    E* e = new E;
    D* d = new D;
    e->I = 3;
    SW1* pc1 = dynamic_cast<SW1*>(d);
    pc1->I = 2;
    std::cerr << d->I;
    std::cerr << e->I;
    SW2* pc2 = dynamic_cast<SW2*>(e);
    pc2->I = 1;
    std::cerr << d->I;
    std::cerr << e->I;
}
c++ multiple-inheritance
3个回答
2
投票

编译器是不正确的诊断你的代码的任何问题。该代码,因为你已经构建它一点也不含糊。从本质上讲,一个名称不明确,如果它是一个以上的变量(或类成员在你的情况)同样很好的匹配。

当评估e->I,发现第一候选是类I的成员(通过继承)的SW2I的那SW2从它的基类继承的成员是不如匹配如由Sw2直接定义的构件。

类似地,pc1->I是明确SW1的构件,d->I是相同的,并且是pc2->I明确的基类SW2的构件。

如果e->I没有自己的成员命名SW2歧义会发生在评估I(即struct SW2: HW, Other {};(在这种情况下,评估e->I时,名称解析看起来SW2的成员名为I,并没有找到它。解决的名则认为这两个基类,HWOther,这两者有一个成员叫I他们同样精彩的比赛,所以表达e->I是模糊的 - 编译器会发出诊断即错误(不只是一个警告)。在这种情况下,有可能程序员明确解决使用范围(::)操作的模糊性。例如,e->HW::Ie->Other::I充分资格的名称。

你是正确的,一类层次结构中的名称,例如多使用是一个坏主意。这既是因为它可能很难正确解决的方式,有意义的编译器的不确定性,因为凡人往往有逻辑如下麻烦。


4
投票

为什么编译器不会写出至少一个警告?

因为你没有写任何错误,危险或不明确的。你或我可能会混淆,但是编译器有一组特定的查找规则来处理它。

当你写像e->I类成员访问表达式,编译器不只是看这名字I,它查找子对象,其中包含这样命名的成员,该成员一起。它也开始用最派生的对象类型,并查找“向上”在基类的子对象,直到找到的东西(这也是如何使会员名躲藏在C ++的工作,简而言之)。

因此,对于e->I,它会在I E。该搜索发现什么都没有,所以它进入的基类主题。它发现SW2::I,是指SW2定义的唯一成员的名称。因此,它停止。

如果没有SW2::I,它会继续寻找和发现都Other::IHW::I。现在同样的名称在两个不同的基类的子对象中,我们得到一个模棱两可。不是模糊的警告,但平坦出来使表达e->I暧昧,这是一个错误。


1
投票

变量未合并,只需让他们的所有3个在同一时间。您需要将指针转换为正确的类型来访问你想要的变量。

#include <iostream>
struct Other { int I; };
struct HW { int I; };
struct SW1 : public Other, public HW { int I; };
struct D : public SW1 { };

int main() {
    D* d = new D;
    d->I = 1;
    SW1* pc1 = dynamic_cast<SW1*>(d);
    pc1->I = 2;
    static_cast<Other*>(pc1)->I = 3;
    static_cast<HW*>(pc1)->I = 4;
    std::cerr << d->I;
    std::cerr << static_cast<Other*>(d)->I;
    std::cerr << static_cast<HW*>(d)->I;
}

打印:

234

即同一个对象d包含3个不同版本I,这取决于你如何看待它。

© www.soinside.com 2019 - 2024. All rights reserved.