2017-01-05 1 views
0

У меня есть код:Конструктор шаг

#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)() деньги в банке, но я не могу. Я мог бы создать класс со структурой Impl и unique_ptr для обучения. Я знаю, что уникальный не может копировать. Как я могу сделать эту программу? Остальная часть моего кода хорошо?

Ошибка

C2027 Ошибка использование неопределенного типа Error 'Банк :: PropertiesBank'
C2039 'ReturnValue': не является членом 'STD :: unique_ptr>'

+2

Когда вы говорите, что вы «не можете», что вы подразумеваете под этим? Вы получаете ошибки сборки? Ошибки во время выполнения или сбои? Неожиданные результаты? Пожалуйста, дополните! А также, пожалуйста, [читайте о том, как задавать хорошие вопросы] (http://stackoverflow.com/help/how-to-ask). –

+1

Поскольку вы хотите определить 'PropertiesBank' вне класса, вам также нужно определить функцию, которая использует ее вне класса: ее реализация должна быть после определения структуры. С этим изменением [ваш код компилируется] (http://rextester.com/UVFJ63318) –

+1

А, создайте ошибки. Затем отредактируйте свой вопрос, чтобы включить * полный * и * полный * и * unedited * вывод компилятора. Просто скопируйте-вставьте вывод, когда вы встраиваете в тело вопроса, как текст. –

ответ

1

Its не проблема с std::unique_ptr, ее факт, что вы попытались обратиться к члену объекта, тип которого PropertiesBank, когда компилятор не видел его полного определения. Вы должны переместить определение функции члена вне класса и в точке, где компилятор видел полное определение PropertiesBank:

Посмотреть комментарий в этом фрагменте ниже:

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(); } 
+0

Но переменная «k» имеет значение после построения банка. Что случилось в моем решении? Я думаю, что если я переведу деньги в Банк, то деньги не будут иметь значения. Я прав? – 21koizyd

+1

@ 21koizyd ... Когда вы 'std :: move' от объекта, *** A *** и другого объекта или функции, *** B *** захватывает его с помощью ссылки * rvalue *. Состояние *** A *** полностью зависит от того, что *** B *** решает сделать с ним. Таким образом, состояние «Деньги» после перехода от него зависит от того, что вы сделали с конструктором перемещения. И кстати ... В 'int main()' вашего исходного кода вы не 'std :: move' * k * в * bank * .... Также см. [This] (http: // stackoverflow.com/questions/14679605/do-built-in-types-have-move-semantics) (особенно последнее предложение n Принятый ответ) – WhiZTiM

+0

Okey, я думал об этой возможности :).Итак, спасибо :) – 21koizyd

2

Единственная проблема, которую я вижу в том, что определение Bank::returnMoney пытается получить доступ к Bank::PropertiesBank, если он только был объявлен вперед, а не определен. Перемещение PropertiesBank будет определено наклон в пределах Bank.

Однако, как мычание Duck указывает в комментариях, если ваше намерение осуществить pImpl idiom, то оба Bank::PropertiesBank и Bank::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; 
} 
+1

Нарушает цель [pImpl] (http://stackoverflow.com/questions/60570/why-should-the-pimpl-idiom-be-used). Правильный ответ - переместить определение 'returnMoney' –

+0

Это правда. В ответе исправлено это. –

 Смежные вопросы

  • Нет связанных вопросов^_^