繁体   English   中英

派生类的副本构造函数(C ++)的初始化列表上的基类

[英]Base class on the initialisation list of a derived class' copy constructor (C++)

让示例为:

class Base {
  Base (const Base & copyFrom) { globalRegister (* this); }
}

class Derived {
  Derived (const Derived & copyFrom) : Base (copyFrom) {}
}

我已经阅读了一些建议,以便将Base的副本构造函数包括在Derived的初始化列表中,以便复制Base的属性(如示例中所示)。

但是,我有Base的副本构造函数将自身(*此)传递给其他对象(向该对象注册)。 在实际存在对象的情况下,实际上我必须在Derived的复制构造函数的初始化列表上使用(隐式或显式)Base的(默认)构造函数,并且仅在Derived的复制构造函数的主体中调用Base的复制构造函数的情况可以由Base的复制构造函数附加? 否则-(*这)是有效的对象吗?

在实际存在对象的情况下,实际上我必须在Derived的复制构造函数的初始化列表上使用(隐式或显式)Base的(默认)构造函数,并且仅在Derived的复制构造函数的主体中调用Base的复制构造函数的情况可以由Base的复制构造函数附加?

您到底为什么要这样做?
(哦,您不能从派生类的构造函数的主体中调用基类的副本构造函数。只能从其初始化列表中调用。)

否则-(*这)是有效的对象吗?

基数的初始化列表完成后,基数的所有成员(和基类)均已完全构建。 但是,类本身仅在构造函数完成后才完全构建。
更重要的是,派生类的构造函数甚至还没有开始,因此该对象还不是派生类的对象。

因此,无论该注册函数执行什么操作,都必须考虑到该对象的动态类型是base类型,并且其构造函数尚未完成。 (为了安全起见,它所能做的就是将对象的地址存储在某个位置。)

仅供参考,该行为由C ++ 03的§12.7 2-3指定:

2)要将表示X类对象的指针(左值)显式或隐式转换为X的直接或间接基类B的指针(引用),X的构造及其所有直接或间接的构造直接或间接从B派生的间接基础将已经开始,并且这些类的销毁还没有完成,否则转换将导致不确定的行为。

this是指向Derived的指针。 Base::Base()this其隐式转换为Base* ,这是允许的,因为Derived的构造已经开始,并且没有其他可从Base派生的Base

第12.7 2节继续:

为了形成指向对象obj的直接非静态成员的指针(或访问其值),应开始obj的构造,并且其销毁还应完成,否则将计算指针值(或访问成员值)导致未定义的行为。

最后,§12.7 3也很重要:

3)成员函数,包括虚拟函数(10.3),可以在构造或销毁过程中调用(12.6.2)。 当从构造函数(包括从数据成员的mem-initializer )或析构函数直接或间接调用虚函数,并且调用所应用的对象是正在构造或销毁的对象时,所调用的函数是一个在构造函数或析构函数自己的类中或在其基类之一中定义的函数,但不是在从构造函数或析构函数的类派生的类中覆盖它的函数,或在大多数派生对象的其他基类之一中覆盖它的函数(1.8)。 如果虚拟函数调用使用显式的类成员访问(5.2.5),并且object-expression表示正在构造或销毁的对象,但其类型既不是构造函数或析构函数自己的类,也不是其基类之一,则结果为通话未定义。

这两个子句表示,一旦Base构造函数开始,尽管Derived实例处于完全不一致的状态,但它是成熟的Base

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM