c++ - 如果有成员,则基类中的默认析构函数禁用子类中的移动构造函数
问题描述
为什么默认的(用户声明的)析构函数会Base1
阻止在类中生成移动构造函数/运算符,但是当我将成员从 Base ( ) 移动到 Child ( ) 类Child1
时一切正常?data
Base2
Child2
struct Data {
Data() {}
Data(Data&&) noexcept { cout << "Move constructor" << endl; }
Data& operator=(Data&&) noexcept {
cout << "Move assign" << endl;
return *this;
}
vector<int> vec;
};
struct Base1 {
virtual void fun() { cout << "Base1::fun" << endl; }
virtual ~Base1() = default;
Data data;
};
struct Child1 : public Base1 {
void fun() override { cout << "Child1::fun" << endl; }
};
struct Base2 {
virtual void fun() { cout << "Base2::fun" << endl; }
virtual ~Base2() = default;
};
struct Child2 : public Base2 {
void fun() override { cout << "Child2::fun" << endl; }
Data data;
};
int main() {
Child1 c1;
auto obj1 = std::move(c1); // error
Child2 c2;
auto obj2 = std::move(c2);
}
我目前的理解是,当我在 Base() 中将析构函数声明为“<code>default”时BaseDel
,移动构造函数应该在 Base( BaseDel
) 和 Child( ChildDel
) 类中为“<code>deleted”。这个对吗?我认为,会员位置应该不重要。如果我明确地这样做,我会得到预期的错误:
struct BaseDel {
BaseDel() {}
virtual void fun() { cout << "BaseDel::fun" << endl; }
BaseDel(BaseDel&& st) = delete;
virtual ~BaseDel() = default;
};
struct ChildDel : public BaseDel {
ChildDel() {}
void fun() override { cout << "ChildDel::fun" << endl; }
Data data;
};
int main() {
ChildDel cd;
auto objd = std::move(cd); // OK, expected error
}
解决方案
隐式移动构造函数不是(仅)被删除的,当你有一个用户声明的析构函数时,它不是首先声明的,就像Base1
and的情况一样Base2
。
因此,在重载决议中永远不能考虑移动构造函数,因此auto obj1 = std::move(c1);
,虽然它可以调用Child1
的移动构造函数,但需要回退到Base1
子对象的复制构造。
Base1
和的隐式声明的复制构造函数Child1
被定义为已删除,因为Data
的隐式声明的复制构造函数被定义为已删除,因为Data
具有用户定义的移动构造函数。因此auto obj1 = std::move(c1);
将失败并显示隐式声明的复制构造函数被删除的错误。
因为Base2
复制构造函数没有定义为已删除,因为它没有Data
成员,所以auto obj2 = std::move(c2);
会调用Child2
' 的移动构造函数(它也使用Data
' 的移动构造函数),但对子对象使用复制构造函数。Base2
推荐阅读
- api - 如何将 tomtom 映射包装到引导容器中
- typescript - npm 脚本未正确启动应用程序
- amazon-web-services - 我可以使用现有的 AWS IAM 角色通过 Cloudformation 模板创建 S3 存储桶吗?
- html - 日期选择器在 Shopify 的页面上不起作用
- python - Keras flow_from_dataframe 提供 0 张图片
- firebase - 如何从 firebase_auth 测试“signInWithEmailAndPassword”
- r - 具有环境的可重现 saveRDS
- angular - 从 Angular 4 转换到 Angular 7 时如何实现“URLSearchParams”和“RequestOptions”
- laravel - 宅基地不想正常开始
- laravel - 如果在 Laravel 中则需要