基类中的默认析构函数禁用子类中的移动构造函数(如果有成员)

Defaulted destructor in base class disable move constructor in child class if there is a member

本文关键字:如果 构造函数 成员 子类 析构函数 默认 基类 移动      更新时间:2023-10-16

为什么Base1中的默认(用户声明(析构函数阻止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(BaseDel(中将析构函数声明为"default"时,移动构造函数在Base(BaseDel(和子(ChildDel(类中应该是"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
}

隐式移动构造函数不会(仅(被删除,当您拥有用户声明的析构函数时,它不会首先声明,就像Base1Base2一样。

因此,移动构造函数永远不能在重载分辨率中考虑,因此auto obj1 = std::move(c1);虽然它可以调用Child1的移动构造函数,但需要回退到Base1子对象的复制构造。

Base1Child1的隐式声明的复制构造函数都定义为已删除,因为Data的隐式声明的复制构造函数被定义为已删除,Data因为它具有用户定义的移动构造函数。因此,auto obj1 = std::move(c1);将失败,并显示删除隐式声明的复制构造函数的错误。

对于Base2,复制构造函数未定义为已删除,因为它没有Data成员,因此auto obj2 = std::move(c2);将调用Child2的移动构造函数(它也使用Data的移动构造函数(,但对Base2子对象使用复制构造函数

相关文章: