来自基础 class 的复制构造函数
Copy-constructor from base class
我有以下代码:
#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
cannot be copy-constructed (for return from make_b
), because it has no copy-constructor, because A
的复制构造函数被删除。
B(const A&)
不符合复制构造函数的条件吗?这里适用的规则是什么?
- 复制和移动构造函数是否总是必须接受一个相同类型的参数(而不是超类)?
- 它可以有默认值的附加参数吗?
- 能否对其进行模板化以便解析为有效的复制构造函数?
- 要允许隐式复制和移动构造,是否有必要显式添加复制和移动构造函数
B(const B&)
和B(B&&)
?
Does B(const A&) not qualify as copy-constructor, and what is the rule that applies here?
没有。复制构造函数创建另一个 相同类型 的对象。 A
与 B
不是同一类型。如果您尝试从其基础 class 的对象构造派生 class 的对象,您应该如何初始化派生 class' 成员?您从中复制的源对象没有要复制的成员!
此外,B
已经有一个复制构造函数,由编译器隐式声明,但是因为隐式定义的格式不正确(因为基 class A
不可复制)被编译器删除,所以不能使用。
Does the copy and move constructor always have to take one argument of the same type (and not a superclass)?
不一定是一个参数,B(const B&, int = 0)
是一个拷贝构造函数,因为调用它可以创建一个B
的拷贝。但是 B(const A&)
不是复制构造函数。
Can it have additional parameters with default values?
是的。
To allow implicit copy and move construction, is it necessary to explicitly add copy and move-constructors B(const B&)
and B(B&&)
?
是的,您需要显式定义它们,因为编译器将使用的隐式定义将不起作用。
由于您的派生类型没有任何成员,并且您已经拥有采用 A
的构造函数,您可以像这样定义它们:
B(const B& b) : B(static_cast<const A&>(b) { }
B(B&& b) : B(static_cast<A&&>(b) { }
这会创建委托构造函数,它只是将参数转发给您现有的构造函数(对基类型使用合适的强制转换)。
约 1 人:
在构造时,编译器会从最高位到当前构造的-class逐个调用所有基class。
如果C继承自B继承自A
编译器调用 A() 然后 B() 而不是 C() ctros 以构建 C 对象。
复制构造函数也是如此:
在您的示例中,您调用了 A() 复制构造函数来构建对象的 "A" 部分,但您删除了它。
这里的问题是按值返回B,如果退出则调用move ctor,否则调用move ctor。你删除了两个
我有以下代码:
#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
cannot be copy-constructed (for return from make_b
), because it has no copy-constructor, because A
的复制构造函数被删除。
B(const A&)
不符合复制构造函数的条件吗?这里适用的规则是什么?- 复制和移动构造函数是否总是必须接受一个相同类型的参数(而不是超类)?
- 它可以有默认值的附加参数吗?
- 能否对其进行模板化以便解析为有效的复制构造函数?
- 要允许隐式复制和移动构造,是否有必要显式添加复制和移动构造函数
B(const B&)
和B(B&&)
?
Does B(const A&) not qualify as copy-constructor, and what is the rule that applies here?
没有。复制构造函数创建另一个 相同类型 的对象。 A
与 B
不是同一类型。如果您尝试从其基础 class 的对象构造派生 class 的对象,您应该如何初始化派生 class' 成员?您从中复制的源对象没有要复制的成员!
此外,B
已经有一个复制构造函数,由编译器隐式声明,但是因为隐式定义的格式不正确(因为基 class A
不可复制)被编译器删除,所以不能使用。
Does the copy and move constructor always have to take one argument of the same type (and not a superclass)?
不一定是一个参数,B(const B&, int = 0)
是一个拷贝构造函数,因为调用它可以创建一个B
的拷贝。但是 B(const A&)
不是复制构造函数。
Can it have additional parameters with default values?
是的。
To allow implicit copy and move construction, is it necessary to explicitly add copy and move-constructors
B(const B&)
andB(B&&)
?
是的,您需要显式定义它们,因为编译器将使用的隐式定义将不起作用。
由于您的派生类型没有任何成员,并且您已经拥有采用 A
的构造函数,您可以像这样定义它们:
B(const B& b) : B(static_cast<const A&>(b) { }
B(B&& b) : B(static_cast<A&&>(b) { }
这会创建委托构造函数,它只是将参数转发给您现有的构造函数(对基类型使用合适的强制转换)。
约 1 人: 在构造时,编译器会从最高位到当前构造的-class逐个调用所有基class。 如果C继承自B继承自A 编译器调用 A() 然后 B() 而不是 C() ctros 以构建 C 对象。
复制构造函数也是如此: 在您的示例中,您调用了 A() 复制构造函数来构建对象的 "A" 部分,但您删除了它。
这里的问题是按值返回B,如果退出则调用move ctor,否则调用move ctor。你删除了两个