在初始化列表中使用超类的地址/指针

发布于 2024-08-28 16:22:21 字数 257 浏览 5 评论 0原文

上下文1:类D:公共B1,公共B2{};

上下文 2: B2 使用 B1 进行初始化: B2( B1 * ) //B2 的构造函数

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

D::D() : B1(), B2( ? )... 应该是什么在?

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

我应该怎么办 ?

context 1: class D : public B1, public B2{};

context 2: B2 takes B1 to initialize: B2( B1 * ) //B2's constructor

my question is in D's initialization list:

D::D() : B1(), B2( ? )... What should be in ?

I don't want to put " (B1*)this " in the ? place, because it's no good to use "this" in initialization list. And since B1 part has been initialized, it makes sense to use it.

What should I do ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月依秋水 2024-09-04 16:22:21

可以使用 thisB1 部分,因为它已经初始化了。 §12.6.2/5:“直接基类应按照它们出现在基说明符列表中的声明顺序进行初始化(无论 mem 初始化程序的顺序如何)。”

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

不过,我想说这有“代码味道”。

编辑:现在我理解您的担忧,this 是否在构造函数主体之外未定义,其中不包括成员初始值设定项。允许这样做的语言隐藏在两个示例之间,我一开始就错过了它。第 7 段:“mem-initializer 的表达式列表中的名称在构造函数的范围内求值,该构造函数的范围是
指定了 mem-initializer。”

如果 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.

It's OK to use the B1 part of this because it is already initialized. §12.6.2/5: "direct base classes shall be initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers)."

The base-specifier-list here is is class D : public B1, public B2, and the mem-initializer-list is D::D() : B1(), B2( … ).

I would say that this has "code smell," though.

EDIT: Now I understand your concern, whether this is undefined outside the body of the constructor, which doesn't include the member initializers. The language allowing this is buried between two examples and I missed it at first. Paragraph 7: "Names in the expression-list of a mem-initializer are evaluated in the scope of the constructor for which the
mem-initializer is specified."

If B2 actually needs to retain a pointer to a B1, and that pointer will always point inside the most-derived object, consider virtual inheritance.

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.
夏末 2024-09-04 16:22:21

这是有风险的代码。正如之前指出的,B1 在 B2 之前构造,因此您可以安全地执行此操作,但如果类定义发生更改,情况将不再如此,并且它位于代码中不相关的位置,因此您看不到当你破坏它时你正在破坏的代码。

我会仔细研究这个设计 - 是否可以对其进行更改以使其变得不必要?您能否将事物移至成员中进行封装而不是继承 - D 真的是 B1 和 B2 吗?

This is risky code. As pointed out before, B1 is constructed before B2, so you can safely do this, but if the class definition changes that will no longer be the case, and it is in an unrelated place in the code, so you can't see the code you're breaking when you break it.

I'd look closely at this design - Is it possible to change it to make this unnecessary? Can you move things into members to encapsulate rather than inherit - is D really a B1 and a B2?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文