Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 派生类初始化列表上的基类';复制构造函数(C+;+;)_C++_Oop_Copy Constructor_Derived_Inherited - Fatal编程技术网

C++ 派生类初始化列表上的基类';复制构造函数(C+;+;)

C++ 派生类初始化列表上的基类';复制构造函数(C+;+;),c++,oop,copy-constructor,derived,inherited,C++,Oop,Copy Constructor,Derived,Inherited,举个例子: class Base { Base (const Base & copyFrom) { globalRegister (* this); } } class Derived { Derived (const Derived & copyFrom) : Base (copyFrom) {} } 我已经阅读了一些建议,建议将基的复制构造函数包括在派生的初始化列表中,以便复制基的属性(如示例所示) 但是,我让基的复制构造函数将自身(*this)传递给其他对象(要

举个例子:

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

class Derived {
  Derived (const Derived & copyFrom) : Base (copyFrom) {}
}
我已经阅读了一些建议,建议将基的复制构造函数包括在派生的初始化列表中,以便复制基的属性(如示例所示)

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

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

你到底为什么要这么做?
(哦,你不能调用基类“从派生类复制构造函数”构造函数的主体。只能从它的初始化列表中调用。)

Else-(*这)是有效对象吗

当基类的初始化列表完成时,所有基类的成员(和基类)都被完全构造。然而,类本身只有在其构造函数完成后才能完全构造。
更重要的是,派生类的构造函数还没有启动,因此该对象还不是派生类的对象

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

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

你到底为什么要这么做?
(哦,你不能调用基类“从派生类复制构造函数”构造函数的主体。只能从它的初始化列表中调用。)

Else-(*这)是有效对象吗

当基类的初始化列表完成时,所有基类的成员(和基类)都被完全构造。然而,类本身只有在其构造函数完成后才能完全构造。
更重要的是,派生类的构造函数还没有启动,因此该对象还不是派生类的对象


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

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

2) 要显式或隐式地将引用类X的对象的指针(左值)转换为指向直接或间接基类B的指针(引用),X的构造及其直接或间接源自B的所有直接或间接基的构造应已开始,且这些类的破坏不得已完成,否则转换将导致未定义的行为

是指向
派生的
的指针。在
Base::Base()
中,
将此
隐式转换为
Base*
,这是允许的,因为派生的构造已开始,并且它没有从
Base
派生的其他基

§12.7.2继续:

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

最后,§12.7.3也很重要:

3) 构件函数,包括虚拟函数(10.3),可在构造或销毁过程中调用(12.6.2)。当从构造函数(包括数据成员的mem初始值设定项)或析构函数直接或间接调用虚函数时,且调用所应用的对象是正在构造或销毁的对象,调用的函数是在构造函数或析构函数自己的类或其一个基类中定义的函数,但不是在从构造函数或析构函数的类派生的类中重写它的函数,也不是在派生最多的对象(1.8)的其他基类之一中重写它的函数。如果虚拟函数调用使用显式类成员访问(5.2.5),并且对象表达式引用正在构造或销毁的对象,但其类型既不是构造函数或析构函数自己的类,也不是其基之一,则调用的结果是未定义的


这两个子句意味着
Derived
的实例在
Base
构造函数开始时是一个成熟的
Base
,尽管它可能处于不一致的状态

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

2) 要显式或隐式地将引用类X的对象的指针(左值)转换为指向直接或间接基类B的指针(引用),X的构造及其直接或间接源自B的所有直接或间接基的构造应已开始,且这些类的破坏不得已完成,否则转换将导致未定义的行为

是指向
派生的
的指针。在
Base::