如果有成员,基 class 中的默认析构函数禁用子 class 中的移动构造函数
Defaulted destructor in base class disable move constructor in child class if there is a member
为什么 Base1
中的默认( 用户声明)析构函数阻止在 Child1
class 中生成移动 constructor/operator,但是当我将成员 data
从 Base (Base2
) 移动到 Child (Child2
) class?
时一切正常
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
”时,那么move构造函数在Base(BaseDel
中应该是“deleted
” =]) 和儿童 (ChildDel
) class。这个对吗?我认为,成员位置无关紧要。如果我明确地这样做,我会得到预期的错误:
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
和 Base2
.
因此在重载决议中永远不会考虑移动构造函数,因此 auto obj1 = std::move(c1);
,虽然它可以调用 Child1
的移动构造函数,但需要回退到 [=10 的复制构造=] 子对象。
Base1
和Child1
的隐式声明的复制构造函数都被定义为已删除,因为Data
的隐式声明的复制构造函数被定义为已删除,因为Data
有一个用户定义的移动构造函数。因此 auto obj1 = std::move(c1);
将失败并显示隐式声明的复制构造函数被删除的错误。
对于Base2
,复制构造函数未定义为已删除,因为它没有Data
成员,因此auto obj2 = std::move(c2);
将调用Child2
的移动构造函数(也使用 Data
的移动构造函数),但对 Base2
子对象使用 复制构造函数。
为什么 Base1
中的默认( 用户声明)析构函数阻止在 Child1
class 中生成移动 constructor/operator,但是当我将成员 data
从 Base (Base2
) 移动到 Child (Child2
) class?
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
”时,那么move构造函数在Base(BaseDel
中应该是“deleted
” =]) 和儿童 (ChildDel
) class。这个对吗?我认为,成员位置无关紧要。如果我明确地这样做,我会得到预期的错误:
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
和 Base2
.
因此在重载决议中永远不会考虑移动构造函数,因此 auto obj1 = std::move(c1);
,虽然它可以调用 Child1
的移动构造函数,但需要回退到 [=10 的复制构造=] 子对象。
Base1
和Child1
的隐式声明的复制构造函数都被定义为已删除,因为Data
的隐式声明的复制构造函数被定义为已删除,因为Data
有一个用户定义的移动构造函数。因此 auto obj1 = std::move(c1);
将失败并显示隐式声明的复制构造函数被删除的错误。
对于Base2
,复制构造函数未定义为已删除,因为它没有Data
成员,因此auto obj2 = std::move(c2);
将调用Child2
的移动构造函数(也使用 Data
的移动构造函数),但对 Base2
子对象使用 复制构造函数。