C++虚拟基类:不调用父级的复制构造函数
C++ virtual base classes: parent's copy constructor doesn't get called
如下面的代码所示,我有三个类。注意我是如何编写复制构造函数的。
#include <iostream>
class Abstract
{
public:
Abstract(){};
Abstract( const Abstract& other ): mA(other.mA){};
virtual ~Abstract(){};
void setA(double inA){mA = inA;};
double getA(){return mA;};
virtual void isAbstract() = 0;
protected:
double mA;
};
class Parent : public virtual Abstract
{
public:
Parent(){};
Parent( const Parent& other ): Abstract(other){};
virtual ~Parent(){};
};
class Child : public virtual Parent
{
public:
Child(){};
Child( const Child& other ): Parent(other){};
virtual ~Child(){};
void isAbstract(){};
};
int main()
{
Child child1;
child1.setA(5);
Child childCopy(child1);
std::cout << childCopy.getA() << std::endl;
return 0;
}
现在为什么Abstract()
被调用,而不是复制构造器Abstract( const Abstract& other )
时,childCopy
被构造?
Child(other)
不应该调用Parent(other)
吗?Parent(other)
不应该反过来调用Abstract(other)
吗?
虚基类只能由最派生的类初始化。从非最派生类调用虚基类的构造函数将被忽略,并用默认构造函数调用替换。这是为了确保虚拟基子对象只初始化一次:
正确的代码应该将构造函数调用放在最派生的类:Child(Child const& other)
: Abstract(other) // indirect virtual bases are
// initialized first
, Parent(other) // followed by direct bases
{ }
为了正确调用Abstract
的复制构造函数,您需要在Child
的复制构造函数的初始化列表中指定它。
Child( const Child& other ): Abstract(other), Parent(other) {};
演示下面是标准中的相关引语,它指出虚拟基类的构造函数只能在最派生的类中调用。如果没有,则调用默认构造函数(——如果存在)。
(13.1§12.6.2):
在非委托构造函数中,初始化按照以下顺序进行:
- 首先,并且仅适用于最派生类的构造函数(1.8),类中出现的顺序初始化虚基类的有向无环图的深度优先从左到右遍历类的出现顺序为"从左到右"
特别地,这就是为什么您注意到Abstract
的默认构造函数被调用的原因。
相关文章:
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 当从函数参数中的临时值调用复制构造函数时
- 如果有一个模板构造函数只有一个泛型参数,为什么我必须有一个复制构造函数
- 为什么需要复制构造函数,在哪些情况下它们非常有用
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 为什么类中的ostringstream类型的成员会导致";调用隐含删除复制构造函数";错误
- 复制构造函数、赋值运算符C++
- std::ofstream 作为类成员删除复制构造函数?
- 复制构造函数C++无法正确复制指针
- 关于复制构造函数的一个棘手问题
- 为什么调用复制构造函数而不是移动构造函数?
- 填充上编译器生成的复制构造函数之间的不一致
- C++ 对象指针数组的复制构造函数
- C++ 基本 CTOR 说明 - 为什么不调用赋值/复制构造函数
- 防止在复制构造函数中隐式调用基构造函数
- 为用户定义的类正确调用复制构造函数/赋值运算符
- 具有已删除移动和复制构造函数的类的就地构造
- 复制构造函数隐式转换问题
- 复制构造函数中的递归调用