从基类复制构造函数

时间:2015-03-08 12:39:33

标签: c++ class c++11 copy-constructor

我有以下代码:

#include <iostream>
#include <utility>

class A {
public:
    A() { }
    A(const A&, int i) { std::cout << "A copy" << std::endl; }
    A(A&&, int i) { std::cout << "A move" << std::endl; }
    A(const A&) = delete;
    A(A&&) = delete;
};

class B : public A {
public:
    B(int i) { std::cout << "B construct" << std::endl; }
    B(const A& a) : A(a, 1) { std::cout << "B copy" << std::endl; }
    B(A&& a) : A(std::move(a), 1) { std::cout << "B move" << std::endl; }
};


B make_b() {
    return B(1);
}

int main() {
    B b = make_b();
}

编译器错误报告错误B无法复制构造(从make_b返回),因为它没有复制构造函数,因为A的复制构造函数被删除。


  • B(const A&)不符合复制构造函数的要求,这里适用的规则是什么?
  • 复制和移动构造函数是否总是必须使用相同类型的一个参数(而不是超类)?
  • 是否可以使用默认值的其他参数?
  • 可以模板化以便它可以解析为有效的复制构造函数吗?
  • 要允许隐式复制和移动构造,是否有必要显式添加复制和移动构造函数B(const B&)B(B&&)

2 个答案:

答案 0 :(得分:4)

  

B(const A&amp;)是否不符合复制构造函数,这里适用的规则是什么?

没有。复制构造函数创建相同类型的另一个对象。 AB的类型不同。如果您尝试从其基类的对象构造派生类的对象,那么您应该如何初始化派生类的成员?您要复制的源对象没有要复制的成员!

此外,B 已经有复制构造函数,由编译器隐式声明,但因为隐式定义不正确(因为基类A是它是由编译器删除的,所以你不能使用它。

  

复制和移动构造函数是否总是必须使用相同类型的一个参数(而不是超类)?

不一定是一个参数,B(const B&, int = 0)是复制构造函数,因为可以调用它来创建B的副本。但是B(const A&)不是复制构造函数。

  

是否可以使用默认值的其他参数?

  

要允许隐式复制和移动构造,是否有必要显式添加复制和移动构造函数B(const B&)B(B&&)

是的,您需要显式定义它们,因为编译器将使用的隐式定义将不起作用。

由于派生类型没有任何成员,并且您已经拥有了A的构造函数,因此您可以像这样定义它们:

B(const B& b) : B(static_cast<const A&>(b) { }
B(B&& b) : B(static_cast<A&&>(b) { }

这会创建委托构造函数,它只是将参数转发给现有的构造函数(使用适当的强制转换为基类型)。

答案 1 :(得分:0)

大约1: 在构造时,编译器从最高层到当前构造的类一个接一个地调用所有基类。 如果C继承自B继承自A 编译器调用A()然后调用B()而不是C()ctros来构建C对象。

复制构造函数也是如此: 在您的示例中,您调用A()复制构造函数来构建&#34; A&#34;对象的一部分,但你删除了它。

这里的问题是按值退出B,如果退出则调用第一个移动ctor,如果不退出则调用ctor。你删除了两个