复制构造函数不被继承

Posted

技术标签:

【中文标题】复制构造函数不被继承【英文标题】:Copy constructor is not inherited 【发布时间】:2015-04-11 14:45:03 【问题描述】:

我有以下代码:

class C 
public:
    C(int) 
    C(const C&) 
    C() 
;  

class D : public C  
public:
    using C::C;
;  

int main() 
    C c;
    D d_from_c(c); // does not compile, copy ctor is not inherited
    D d_from_int(1); // compiles, C(int) is inherited
   

派生类应该继承除默认ctor之外的所有基础ctor(解释here)。但是为什么copy ctor也没有被继承呢?此处不接受来自相关问题的参数。

代码使用g++ 4.8.1编译。

【问题讨论】:

【参考方案1】:

因为标准是这样说的。 [class.inhctor]/p3,强调我的:

对于继承的候选集中的每个非模板构造函数 构造函数除了没有参数的构造函数或 具有单个参数的复制/移动构造函数,构造函数是 隐式声明具有相同的构造函数特征,除非 有一个用户声明的具有相同签名的构造函数 出现 using 声明或构造函数的完整类 将是该类的默认、复制或移动构造函数。

【讨论】:

此规则已被追溯替换为(当前的)[over.match.funcs]/8。你能更新你的答案吗?【参考方案2】:

派生类应该继承base的所有ctors,除了默认的ctors

不,这不是真的,请参阅T.C.'s answer 了解真正的规则。

继承构造函数的目的是说“派生类型可以从与基类型相同的参数创建”,但这与基类的复制构造函数无关,因为复制构造函数不仅仅是一个表示如何从给定参数创建类型。

复制构造函数比较特殊,它是用来复制一个相同类型的对象。

构造函数D(const C&) 不会用于复制相同类型的对象,因为CD 的类型不同。

【讨论】:

这个说法是有缺陷的,同理,继承的基类ctor在语义上只负责初始化基子对象,继承的基类拷贝ctor也负责初始化基子对象-目的。无论初始化是来自一组参数还是“其他”对象都无关紧要,后者是前者的特例。我认为这种限制的真正原因是“只是为了谨慎”,尽管我真的不明白他们在谨慎什么。 没有复制构造函数负责通过调用基础复制构造函数来初始化基础部分。不过,您不需要继承 ctor。【参考方案3】:

暂时,我们假设允许“复制构造函数继承”。 保持您的类结构完整,请考虑修改 main 方法的以下代码。

int main() 
    C c;
    D d;
    D d_from_d(d);
    D d_from_c(c); // does not compile, copy ctor is not inherited
    D d_from_int(1); // compiles, C(int) is inherited
  

D d_from_d(d)中,作为普通的构造函数调用,会有两次拷贝构造函数调用。一个用于 C::C(const C&),另一个用于编译器为 D 生成的复制构造函数。在 D 中具有源对象类型(在本例中为 d),C 的复制构造函数可以复制 d 的 C 属性,而编译器生成 D 的复制构造函数可以复制d的D属性。

但是在D d_from_c(c)的情况下,C的拷贝构造函数没有问题,因为c的C属性可以被C的拷贝构造函数拷贝。但是编译器如何生成 D 的复制构造函数,知道如何从 C 的对象中复制“D 的属性”。这是一个应该避免的冲突。

但是,如果您提供某种“奇怪的复制构造函数”(您可能还需要默认构造函数),例如;

D(const C & c):C(c) 

那么, 打电话给D d_from_c(c); 已验证。因为,现在我们已经显式地提供了一个匹配的“复制”构造函数。

因此,说“现在允许继承复制构造函数”是无效的。

【讨论】:

以上是关于复制构造函数不被继承的主要内容,如果未能解决你的问题,请参考以下文章

删除复制构造函数会破坏继承的构造函数

Java构造函数继承

C++在单继承多继承虚继承时,构造函数复制构造函数赋值操作符析构函数的执行顺序和执行内容

虚拟继承、默认构造函数和额外复制

复制构造函数无法识别继承的成员

C++ - 继承,调用哪个基本构造函数? [复制]