微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用删除默认构造函数的移动构造函数

如何解决如何使用删除默认构造函数的移动构造函数

我有一段这样的现有代码

struct Base {
    Base() = default;
};

struct Derive: public Base
{
    Derive() = default;
    Derive(const Derive&) = delete;
    Derive(Derive&& p) { *this = std::move(p); }
    Derive& operator = (const Derive& p) = delete;
    Derive& operator = (Derive&& p) {
        return *this;
    }
};

int main() {
  Derive p;
}

它可以编译并运行。现在我想稍微更改类定义,以便 Base 或 Derived 类始终使用特定的整数参数构造,并且永远不会在没有此类参数的情况下构造。

因此,如果我尝试以下更改:

struct Base {
    Base() = delete;
    Base(int a_) : a{a_} {};
private:
  int a; //new mandatory param;
};

struct Derive: public Base
{
    Derive() = delete;
    Derive(int a_) : Base(a_) {};
    Derive(const Derive&) = delete;
    Derive(Derive&& p) { *this = std::move(p); }
    Derive& operator = (const Derive& p) = delete;
    Derive& operator = (Derive&& p) {
        return *this;
    }
};

int main() {
  Derive p{1};
}

我收到编译错误

main.cpp:15:2: error: call to deleted constructor of 'Base'
        Derive(Derive&& p) { *this = std::move(p); }
        ^
main.cpp:4:2: note: 'Base' has been explicitly marked deleted here
        Base() = delete;
        ^
1 error generated.

显然这种方式行不通。那么我该如何修改代码以使其能够编译并且不会无误地调用任何参数构造函数

解决方法

问题

Derive(Derive&& p) xxx { *this = std::move(p); }

是在 xxx 部分您有一个空的 member initialization list。这意味着编译器将为您插入一个基类,因为在执行构造函数体之前,所有成员都在成员初始化列表中进行了初始化。编译器生成的版本看起来像

Derive(Derive&& p) : Base() { *this = std::move(p); }

而且您不能执行 Base(),因为它已被删除。你想要的是

Derive(Derive&& p) : Base(std::move(p)) {}

甚至更短

Derive(Derive&& p) = default;
,

您不需要显式删除基类中的默认构造函数。简单地定义一个需要参数的 ctor 可以防止编译器生成默认的 ctor,因此您的基类可以是:

struct Base {
    Base(int a_) : a{a_} {};
private:
  int a; //new mandatory param;
};

同样,在您的派生类中,定义一个接受参数的 ctor 会阻止编译器为其生成默认 ctor。至少到目前为止,您提到的任何内容似乎都没有表明您需要为派生类显式定义任何特殊成员函数,因此它可以变得简单:

struct Derive: public Base
{
    Derive(int a_) : Base(a_) {};
};

...现在代码编译得很好,任何尝试创建 BaseDerive 的实例而不指定 ctor 的参数都将失败(不会编译)。

顺便说一句,由于您将它用作基类,您可能希望 Base 使其 dtor 成为虚拟的。在这里将其定义为默认值可能是合适的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。