21koizyd
21koizyd

Reputation: 2013

Constructor move

I have a code:

#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;
}

I want display(returnMoney()) money in the Bank, but I can't. I could make class with struct Impl and unique_ptr for training. I know, that unique can't copy. How can I make this programm? Are the rest of my code is well?

Error

Error C2027 use of undefined type 'Bank::PropertiesBank' Error
C2039 'returnValue': is not a member of 'std::unique_ptr>'

Upvotes: 0

Views: 96

Answers (2)

David Scarlett
David Scarlett

Reputation: 3341

The only issue I can see is that the definition of Bank::returnMoney tries to access Bank::PropertiesBank when it has only been forward-declared, not defined. Moving PropertiesBank to be defined incline within Bank fixes this.

However as Mooing Duck points out in the comments, if your intention is to implement the pImpl idiom, then both Bank::PropertiesBank and Bank::returnMoney should be defined in a .cpp file, rather than within the class definition.

#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;
}

Upvotes: 2

WhiZTiM
WhiZTiM

Reputation: 21576

Its not a problem with std::unique_ptr, its the fact that you tried accessing a member of an object whose type is PropertiesBank when the compiler hasn't seen its full definition. You should move the definition of the member function outside the class and at the point where the compiler has seen the full definition of PropertiesBank:

See the comment in this snippet below:

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)) {};
};

You should move the function's definition to after where the compiler has seen the definition of the type of 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(); }

Upvotes: 1

Related Questions