【问题标题】:Constructor move构造函数移动
【发布时间】:2017-01-05 00:18:40
【问题描述】:

我有一个代码:

#include "stdafx.h"
#include "memory"
#include <gtest\gtest.h>
class Money
{
public:
    explicit Money(int value) :value(value) {} ;
    Money(Money&& m) :value(m.returnValue()) {};
    Money(const Money &m) = default;
    Money operator-(const Money &m) ;
    Money &operator=(Money &&m) { return Money(m.returnValue()); };
    Money &operator=(const Money &m)=default;
    int returnValue() const { return value; };
    ~Money() = default;
private:
    int value;
};
Money Money::operator-(const Money &m)
{
    return Money(value - m.returnValue());
}


class Bank {
public:
    Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
    int returnMoney() const { return propertiesBank->money->returnValue(); }
    ~Bank() = default;
private:
    struct PropertiesBank;
    std::unique_ptr<PropertiesBank> propertiesBank;
};

struct Bank::PropertiesBank
{
    std::shared_ptr<Money> money;
    PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};
int main()
{
    Money k(1000);
    Bank bank(k);
    return 0;
}

我想在银行显示(returnMoney()) 钱,但我不能。我可以使用 struct Impl 和 unique_ptr 进行培训。 我知道,那独一无二的无法复制。 我怎样才能制作这个程序? 我的其余代码都好吗?

错误

错误 C2027 使用未定义类型 'Bank::PropertiesBank' 错误
C2039 'returnValue': 不是 'std::unique_ptr>' 的成员

【问题讨论】:

  • 当你说你“不能”时,你是什么意思?你有构建错误吗?运行时错误或崩溃?出乎意料的结果?请详细说明!也请read about how to ask good questions.
  • 既然你想在类外定义PropertiesBank,你也需要在类外定义使用它的函数:它的实现必须在结构定义之后。随着这一变化,your code compiles
  • 啊,构建错误。然后编辑您的问题以包含编译器的 fullcompleteunedited 输出。当您构建到问题正文中时,只需将输出复制粘贴为文本。

标签: c++ c++11 move


【解决方案1】:

我能看到的唯一问题是Bank::returnMoney 的定义尝试访问Bank::PropertiesBank,但它只是被前向声明而不是定义。移动 PropertiesBank 以在 Bank 内倾斜定义此问题。

但是正如 Mooing Duck 在 cmets 中指出的那样,如果您的意图是实现 pImpl idiom,那么 Bank::PropertiesBankBank::returnMoney 都应该在 .cpp 文件中定义,而不是在类定义中。

#include <memory>

class Money
{
public:
    explicit Money(int value) :value(value) {} ;
    Money(Money&& m) :value(m.returnValue()) {};
    Money(const Money &m) = default;
    Money operator-(const Money &m) ;
    Money operator==(Money &&m) { return Money(m.returnValue()); };
    int returnValue() const { return value; };
    ~Money() = default;
private:
    int value;
};

Money Money::operator-(const Money &m)
{
    return Money(value - m.returnValue());
}

class Bank {
public:
    Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
    int returnMoney() const { return propertiesBank->money->returnValue(); }
    ~Bank() = default;
private:
    struct PropertiesBank
    {
        std::shared_ptr<Money> money;
        int returnMoney() const { return money->returnValue(); }
        PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
    };

    std::unique_ptr<PropertiesBank> propertiesBank;
};

#include <iostream>

int main()
{
    Money m(10);
    Bank b(m);

    std::cout << b.returnMoney();
    return 0;
}

【讨论】:

  • 违反了pImpl 的意图。正确答案是移动returnMoney的定义
  • 确实如此。修改答案以说明这一点。
【解决方案2】:

这不是std::unique_ptr 的问题,而是当编译器没有看到其完整定义时,您尝试访问类型为PropertiesBank 的对象的成员。您应该将成员函数的定义移到类之外,并且在编译器已经看到 PropertiesBank 的完整定义的位置:

请参阅下面此 sn-p 中的评论:

class Bank {
public:
    Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};

    int returnMoney() const;{ return propertiesBank->money->returnValue(); }
    // .......The compiler doesn't know that `money`^^^^^^ belongs to `PropertiesBank`

    ~Bank() = default;
private:
    struct PropertiesBank;
    std::unique_ptr<PropertiesBank> propertiesBank;
};

struct Bank::PropertiesBank
{
    std::shared_ptr<Money> money;
    PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};

你应该把函数的定义移到编译器看到propertiesBank类型的定义之后:

class Bank {
public:
    Bank(Money m) :propertiesBank(std::make_unique<PropertiesBank>(std::move(m))) {};
    int returnMoney() const;    //member function declaration
    ~Bank() = default;
private:
    struct PropertiesBank;
    std::unique_ptr<PropertiesBank> propertiesBank;
};

struct Bank::PropertiesBank
{
    std::shared_ptr<Money> money;
    PropertiesBank(Money&& m) :money(std::make_shared<Money>(m)) {};
};

//Member function's definition
int Bank::returnMoney() const { return propertiesBank->money->returnValue(); }

【讨论】:

  • 但变量“k”在构造银行后具有相同的值。我的解决方案有什么问题?我认为,如果我把钱转移到银行,那钱就没有价值了。我是对的?
  • @21koizyd ...当你std::move来自一个对象,A和另一个对象或函数,B 通过 rvalue 引用获取它。 A 的状态完全取决于 B 决定如何处理它。因此,Money 从它移动后的状态取决于您对移动构造函数所做的操作。顺便说一句...在您原始代码的int main() 中,您没有将std::move k 转换为bank .... 另请参阅this(特别是最后一句 n 接受的答案)
  • 好吧,我在考虑这种可能性:)。所以,谢谢:)
猜你喜欢
  • 2011-05-22
  • 2017-11-03
  • 2014-11-08
  • 2020-03-22
  • 1970-01-01
  • 2013-01-03
  • 2018-01-23
  • 2014-03-19
相关资源
最近更新 更多