2010-04-12 29 views
3

上下文1:D类:public B1,public B2 {};在初始化列表中使用超类的地址/指针

背景2:B2采用B1初始化:B2(B1 *)// B2的构造

我的问题是,在D的初始化列表:

d :: d():B1(),B2 (?)... 应该在什么地方?

我不想把 “(B1 *)本” 的?因为在初始化列表中使用“this”并不好。由于B1部分已经初始化,所以使用它是有意义的。

我该怎么办?

回答

3

这是确定使用的thisB1一部分,因为它已经被初始化。 §12.6.2/ 5:“直接基类应按声明顺序进行初始化,因为它们出现在基本说明符列表中(不管mem初始化程序的顺序如何)。”

这里的基地说明符列表是class D : public B1, public B2,而mem-initializer-list是D::D() : B1(), B2(…)

虽然我会说这有“代码味道”。

编辑:现在我明白您的顾虑,this是否在构造函数,它不包括成员初始化的体外不确定的。允许这种语言被埋在两个例子之间,我首先错过了它。第7段:“mem-initializer的表达式列表中的名称将在指定了 mem初始化程序的构造函数的作用域中进行评估。”

如果B2实际上需要保留一个指向B1的指针,并且该指针始终指向派生最多的对象,请考虑虚拟继承。

class B1 {}; 
class B2 : virtual B1 {}; // under the hood, B2 has a pointer to B1. 
class D : public virtual B1, public B2 {}; // D has a pointer too 
// Only the most-derived class (the one actually used for instantiation) 
// implements space for and initialization of the B1. 
+0

对我来说,B1和B2不是继承关系,我不想为了解决这个问题而改变B2。 – 2010-04-12 07:17:40

1

这是有风险的代码。正如前面指出的那样,B1是在B2之前构建的,所以你可以安全地做到这一点,但是如果类定义的改变不再是这种情况,并且它在代码中不相关的地方,所以你看不到当你打破它时你破坏了代码。

我会仔细看看这个设计 - 是否有可能改变它使之变得不必要?你能将事物移入成员来封装而不是继承 - D真的是B1和B2吗?

+0

常见的情况是,一个成员依赖另一个成员,如果定义发生变化,开发人员有责任改变实现。 我可以改变我的设计,这很容易,但我想发现这个问题的技术方面,因为它是有道理的。 – 2010-04-12 07:22:55

+0

@JQ:你说“会员”而不是“基地”。如果他们真的是会员,那么你就没有这个问题。他们? – Potatoswatter 2010-04-12 07:30:27

+0

@Patatoswatter:我再次重复以下内容 “我可以改变我的设计,这很容易,但我想发现这个问题的技术方面,因为它是有意义的” – 2010-04-13 02:25:49