C++ c+中无虚函数的多重继承+;
我遇到了钻石问题,用一颗钻石为不同的案例找到了不同的解决方案。然而,我找不到解决“链”钻石的方法 根据结构:是的,我希望每次都有多个基类,所以虚拟继承不是一个解决方案(它甚至被称为diamond吗?)。我还希望避免为菱形的每个中间层使用get/set函数C++ c+中无虚函数的多重继承+;,c++,inheritance,diamond-problem,C++,Inheritance,Diamond Problem,我遇到了钻石问题,用一颗钻石为不同的案例找到了不同的解决方案。然而,我找不到解决“链”钻石的方法 根据结构:是的,我希望每次都有多个基类,所以虚拟继承不是一个解决方案(它甚至被称为diamond吗?)。我还希望避免为菱形的每个中间层使用get/set函数 p p | | k k \ / s class parent { int val; }; class kid1 : public parent {}; class kid2 : public parent {}; class
p p
| |
k k
\ /
s
class parent { int val; };
class kid1 : public parent {};
class kid2 : public parent {};
class school : public kid1, public kid2 {};
在父类中访问val的工作方式如下:
school* s = new school;
s->kid1::val=1; // works
但下一颗“链锁”钻石呢
p p p p
| | | |
k k k k
\ / \ /
s s
| |
c c
\ /
w
class country1 : public school {};
class country2 : public school {};
class world : public country1, public country2 {};
通过以下方式访问val:
world* w = new world;
w->country1::kid1::val=1; // error
结果:
error: ‘kid1’ is an ambiguous base of ‘world’
为什么??到值的路径不是定义得很好吗?
s->kid1::val
并不意味着“val
来自kid1
子对象”。它只是由包含它的类型(而不是子对象)限定的名称
我不知道为什么country1::kid1
甚至被接受,但显然它是::kid1
的类型定义。world
中的两个数据成员都具有限定名::kid1::val
你想要的是:
world* w = new world;
country1* const c1 = world;
c1->kid1::val = 1;
是的。这个错误是由于编译器中的一个bug造成的。@Nikolay:我想@nem知道这一点。但对于每个国家,我们都有一个明确的基础1。因此有一个问题,为什么这不起作用?我很确定
学校:孩子
关系违反了LSP。至少我从来没有去过一所只有两个孩子的学校:)我担心最终维护这个代码库的人是否理智——这甚至让可怜的Visual Studio发疯。IDE将此注册为错误,但编译器没有。这只是假设:)我有一个不同的实现。@Fred,@Jon:同意,在这里使用组合比使用继承要好得多考虑到我已经解释了代码错误的原因,任何代码正确的声明都应该附带引用C++标准的特定部分,您认为它允许:)3.4.3限定名称查找是非常清楚的。给定w->country1::kid1::val,编译器使用§3.4.5类成员访问来查找country1;根据§3.4.5/4,如果id表达式是限定id(它是),则该查找在类范围和完整表达式的上下文中进行,因此编译器将查找::country1。然后,应用§3.4.3中的常规规则。@詹姆斯:然后再次应用该规则(有两个作用域解析运算符),编译器会找到::kid1
(正如我在回答中所说的)。但是::kid1::val
不明确,编译器是正确的。没有country1::kid1
,除了::kid1
,作用域解析运算符处理类型名称,而不是子对象名称(并且基本子对象没有命名,所以不能说w->country1.kid1.val
)。@Ben Voigt哪个规则?编译器找到country1后,它将进入限定名称查找(§3.4.3),并且不会(或不应该)查找country1以外的任何地方。@James:What isw->country1::kid1
?A型?然后w->country1::kid1::val
是不明确的,因为该类型是world
基类的两倍。子对象?然后用:
跟随它是非法的。