派生类的初始化列表上的基类复制构造函数 (C++)
举个例子:
class Base {
Base (const Base & copyFrom) { globalRegister (* this); }
}
class Derived {
Derived (const Derived & copyFrom) : Base (copyFrom) {}
}
我读过一些建议,将 Base 的复制构造函数包含在 Derived 的初始化列表中,以便复制 Base 的属性(如示例中所示)。
但是,我有 Base 的复制构造函数将其自身 (* this) 传递给其他对象(要向该对象注册)。在这种情况下,我实际上必须在 Derived 的复制构造函数的初始化列表上使用(隐式或显式)Base 的(默认)构造函数,并且仅在实际存在对象时在 Derived 的复制构造函数的主体中调用 Base 的复制构造函数可以通过 Base 的复制构造函数附加吗?否则 - (* this) 是一个有效的对象吗?
Let the example be:
class Base {
Base (const Base & copyFrom) { globalRegister (* this); }
}
class Derived {
Derived (const Derived & copyFrom) : Base (copyFrom) {}
}
I've read suggestions to include the Base's copy constructor on the initialisation list of Derived in order to copy over the Base's properties (as in the example).
However, I have the Base's copy constructor passing itself (* this) to other object (to be registered with that object). Would that be a case where I actually must use (implicitly or explicitly) Base's (default) constructor on the initialisation list of Derived's copy constructor, and call the Base's copy constructor only in the body of Derived's copy constructor, when there is actually an object that can be attached by Base's copy constructor? Else - is (* this) a valid object?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你到底为什么要这么做?
(哦,您不能从派生类的构造函数的主体调用基类的复制构造函数。只能从其初始化列表中调用。)
当基类的初始化列表完成时,基类的所有成员(和基类)都已完全构造完毕。然而,类本身只有在其构造函数完成后才被完全构造。
更重要的是,派生类的构造函数还没有开始,因此该对象还不是派生类的对象。
因此,无论注册函数做什么,它都必须考虑到对象的动态类型是
base
并且其构造函数尚未完成。 (为了安全起见,它所能做的就是将对象的地址存储在某个地方。)Why on earth would you want to do that?
(Oh, and you can not call a base class' copy constructor from a derived class' constructor's body. Only from its initialization list.)
The moment the base's initialization list has completed, all of base's members (and base classes) are fully constructed. The class itself, however, is only fully constructed when its constructor has finished.
More importantly, the derived class' constructor hasn't even started yet, so the object is not a derived class' object yet.
So whatever that registering function does, it has to take into account that the object's dynamic type is
base
and that its constructor hasn't finished yet. (To be safe, all it can do is to store the object's address somewhere.)仅供参考,该行为由 C++03 的 § 12.7 2-3 指定:
this
是一个指向Derived
的指针。在Base::Base()
中,this
被隐式转换为Base*
,这是允许的,因为 Derived 的构造已经开始并且它没有从Base
派生的其他碱基。§ 12.7 2 继续:
最后,§ 12.7 3 也很重要:
这两个子句意味着,一旦
Base
构造函数开始,Derived
的实例就是一个成熟的Base
,尽管它可能处于不一致的状态。Just for reference, the behavior is specified by § 12.7 2-3 of C++03:
this
is a pointer toDerived
. InBase::Base()
,this
is implicitly cast to aBase*
, which is allowed because the construction of Derived has started and it has no other bases that derive fromBase
.§ 12.7 2 continues:
Finally, § 12.7 3 is also important:
These two clauses means an instance of
Derived
is a fully-fledgedBase
once aBase
constructor begins, though it might be in an inconsistent state.