根据“Five of Rule”,当我声明其中一个:复制或移动操作或析构函数时,我必须编写所有这些,因为编译器不会为我生成它们(其中一些)。但是如果我的类(A
)派生自带有虚拟析构函数的抽象类,这是否意味着类A
中的析构函数将被视为"用户定义"?因此,移动语义不适用于此类A
的对象,因为编译器不会为我生成移动构造函数吗?
struct Interface {
virtual void myFunction() = 0;
virtual ~Interface() {};
};
struct A : public Interface {
void myFunction() override {};
};
答案 0 :(得分:11)
在[class.copy]中:
如果类
X
的定义没有显式声明一个移动构造函数,那么将隐式声明一个 当且仅当如此时违约 (9.1) - X没有用户声明的拷贝构造函数,
(9.2) - X没有用户声明的复制赋值运算符,
(9.3) - X没有用户声明的移动赋值运算符,和
(9.4) - X没有用户声明的析构函数。
[注意:当没有隐式声明或显式提供移动构造函数时,否则表达式 会调用移动构造函数可能会调用复制构造函数。 -end note]
Interface
确实有一个用户声明的析构函数,因此Interface
的移动构造函数不会被隐式声明为默认值。但是A
并不适合任何这些项目符号 - 因此将具有默认的隐式移动构造函数。根据说明,A(A&& )
只会复制Interface
部分。我们可以通过向Interface
和A
添加成员来验证这一点:
#include <iostream>
template <char c>
struct Obj {
Obj() { std::cout << "default ctor" << c << "\n"; }
Obj(const Obj&) { std::cout << "copy ctor" << c << "\n"; }
Obj(Obj&&) { std::cout << "move ctor" << c << "\n"; }
};
struct Interface {
virtual void myFunction() = 0;
virtual ~Interface() {};
Obj<'I'> base;
};
struct A : public Interface {
void myFunction() override {};
Obj<'A'> derived;
};
int main() {
A a1; // default I, default A
std::cout << "---\n";
A a2(std::move(a1)); // copy I, move A
std::cout << "---\n";
A a3(a2); // copy I, copy A
}