gpt4 book ai didi

c++ - 添加自定义析构函数时, move 构造函数在派生类中消失

转载 作者:行者123 更新时间:2023-12-02 11:11:58 24 4
gpt4 key购买 nike

我有一个仅 move 的基类和一个继承基类构造函数的派生类。我想为 Derived 提供一个自定义析构函数,但是当我这样做时,它不再继承 Base 的 move 构造函数。非常神秘。发生了什么事?

godbolt

// move-only
struct Base {
Base() = default;
Base(Base const &) = delete;
Base(Base &&) {}
};

struct Derived : public Base {
using Base::Base;

// remove this and it all works
~Derived() { /* ... */ }
};

int main() {
Base b;
// works
Base b2 = std::move(b);

Derived d;
// fails
Derived d2 = std::move(d);
}

最佳答案

move 构造函数并不像您想象的那样通过 using Base::Base; 继承,因为 Base 中的 move 构造函数没有Derived 中的 move 构造函数将具有的签名。前者采用 Base&&,后者采用 Derived&&

然后在 Derived 中声明一个析构函数。这会禁止 Derived 的 move 构造函数的隐式声明。所以Derived中没有 move 构造函数。

然后编译器会回退到 DerivedDerived d2 = std::move(d); 隐式生成的复制构造函数。但它被定义为已删除,因为 Derived 的基类不可复制。 (您手动删除了Base的复制构造函数。)

在重载决策中,会选择删除的复制构造函数而不是基类继承的 Base(Base&&) 构造函数(尽管 Derived 右值可以绑定(bind)到 Base&& code>),因为后者需要一个不被视为完全匹配的转换序列,而绑定(bind)到 const Derived& 则被视为完全匹配重载解析的目的。

还有 CWG issue 2356 决议的拟议措辞这将完全排除继承的 Base move 构造函数参与重载解析。 (据我所知,这是编译器已经实现的。)

如果您没有充分的理由声明析构函数,请不要这样做。如果确实有原因,那么您需要再次默认 move 操作,就像对 Base 中的 move 构造函数所做的那样。 (如果类应该是可分配的,您可能还想默认 move 分配运算符。)

如果您打算多态地使用类层次结构,则应在多态基类中声明一个虚拟(默认)析构函数,但不需要在派生类中声明析构函数。

关于c++ - 添加自定义析构函数时, move 构造函数在派生类中消失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59995794/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com