Инициализированные переменные теряют значения после вызова функции - PullRequest
4 голосов
/ 28 мая 2010

Вопрос говорит сам за себя, правда. Я не уверен, в чем проблема. Я довольно новичок в занятиях; мой практический опыт работы с ними близок к нулю, но я прочитал о них немало.

Я создал класс ECard со следующим конструктором

ECard::ECard( int bankNum, int PIN )
{
    m_BankNum     = new int;
    m_PIN         = new int;
    m_Barred      = new bool;
    m_Amount      = new double;

    *m_BankNum     = bankNum;
    *m_PIN         = PIN;
    *m_Barred      = false;
    *m_Amount      = 100.0;
}

и я инициализирую с EC card( 12345, 54321 )

У меня также есть функция-член display(), которая просто выводит все переменные-члены BankNum, PIN, Barred и Amount.

Когда я вызываю эту функцию card.display () в моей основной функции, вывод получается именно так, как я ожидал.

Однако, когда он входит в мой цикл:

/* Fine values! */
card.display();
while( true )
{
    /* Introductory screen giving user options to choose from */
    mainScreen( card );
    /* Make a choice... */
    choice = readInput();
    /* Garbage! */
    card.display();
    /* Pass it to the switch, watch out for invalid input! doChoice is a bool */
    if( !doChoice( choice, card ) )
    {
        cout << "Bad input- repeat!" << endl;
    }
    /* TODO: Option to terminate loop. */
}

и я пытаюсь напечатать переменные в моей функции doChoice (), я получаю мусор. Все мои переменные испортили настройки. Мой Banknumber - это что-то, PIN-код - это действительно большое отрицательное число (не МИН), для Barred внезапно устанавливается значение true, и на моем счете 0 денег, даже если Barred и Amount никогда не устанавливались мной явно за пределами конструктора.

/* Outsourced switch that handles the user input from MAIN */
bool doChoice( int choice, ECard card )
{
    int inputPIN;
    int inputAmount;

    /* Garbage! */
    card.display();

    switch( choice )
    {
    case 1:
    /* Case 1: Charge card with money. Needs PIN and amount */
        cout << "PIN Eingeben:  ";
        inputPIN    = readInput();
        cout << "\nBetrag Eingeben:  ";
        inputAmount = readInput();

        karte.aufladen( inputAmount, inputPIN );

        return true;

Извините, если некоторые функции-члены и выходы все еще на немецком языке. В любом случае это не должно быть важно (мне все равно нравится писать все домашние задания на английском, поскольку я, вероятно, буду программировать для международных компаний, но мой учитель очень разборчив и понижает мою оценку, если я программирую вне его ожиданий)

Переменные уже перепутаны еще до того, как они попадут в коммутатор, так что часть должна быть просто риторикой. Я вижу проблему только с передачей объекта карты, хотя я не знаю, почему это будет проблемой. Я не знаю, как это исправить, я просто отправляю каждого участника вместо этого? Создать указатель на объект и отправить это? Я имею в виду, что раньше я передавал объект карты, а другая функция не давала мне мусора. Только этот.

И последнее замечание: если внезапно возникает ошибка в синтаксисе, то это потому, что я быстро перевел все свои функции и элементы на английский, и я мог где-то пропустить заглавную букву или еще что-то. Пожалуйста, не обращайте на них внимания, синтаксис правильный и программа запускается, она просто отображает значения мусора.

Ответы [ 3 ]

6 голосов
/ 28 мая 2010

Вы передаете карту по значению. Но поскольку у вас полно указателей, и, вероятно, вы не написали конструктор копирования, копия карточки использует указатели для изменения памяти, которую также использует «старая» карточка в вашем основном цикле. Затем, когда функция завершается, возможно, у вас есть деструктор карты, который удаляет все переменные-члены? Таким образом, у вас в основном есть висячие указатели. Я не могу быть уверен без всего кода для ECard, но это мое предположение.

У меня не было бы указателей на карте. Я не вижу никакой выгоды для int * по сравнению с int там. И затем, так как вы хотите, чтобы doChoice сменил карту, возьмите с собой карту ECard, чтобы она сменила реальную карту, которую вы используете в main.

3 голосов
/ 28 мая 2010

Является ли mainScreen () передачей 'card' в качестве ссылки или по значению? Происходит следующее: вызов создает новую локальную копию и вызывает конструктор по умолчанию, который не выделяет память и не инициализирует локальные переменные. То же самое происходит с doChoice (). Передайте по ссылке в обеих этих функциях, и это должно решить эту проблему.

т.е. - bool doChoice (на выбор, электронная карта и карта)

1 голос
/ 28 мая 2010

Не размещать переменные динамически, если это не нужно

В языке Java экземпляры переменных определяются с помощью оператора new. Это не обязательно в C ++.

Измените объявление класса на:

struct ECard
{
    ECard(unsigned int bankNum,
          unsigned int newPIN)
    : m_bankNum(bankNum),
      m_pin(newPIN),
      m_barred(false),
      m_amount(100.0)
  {
    ;
  }

  unsigned int m_bankNum; // Can bank numbers be negative???
  unsigned int m_pin;
  bool         m_barred;
  double       m_amount;
};

1009 * Pointers * Если вам действительно нужно динамически распределять память для членов, используйте умные указатели. Умные указатели автоматически освобождают память при необходимости. Я предлагаю использовать библиотеку Boost. Если вы не можете использовать умные указатели, не забудьте освободить память в деструкторе: ECard:: ~ECard() { delete m_p_bankNum; delete m_p_pin; delete m_p_barred; delete m_p_amount; } Если вы не используете указатели в своем классе или структуре, вы избегаете хлопот динамического выделения и освобождения памяти, особенно для копирования и уничтожения (кому принадлежит память?).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...