Идентификатор C «_var» не определен

#c #undefined #identifier

#c #не определено #идентификатор

Вопрос:

Я пытаюсь выучить C (в настоящее время знаю только PHP и немного C #) и столкнулся со своей первой проблемой.

Я пытаюсь вызвать класс внутри коммутатора, а затем использовать эту определенную переменную после переключения. Однако я получаю ошибку, описанную в названии.

 #include <iostream>
#include <string>

using namespace std;

class Hero {
protected:
    int hHealth,hStamina,hExp;
    string hName;
public:
    void Create(string);
    string GetName() {
        return this->hName;
    }
};

class Wizard:public Hero {
public:
    void SetStats(string hName) {
        this->hName = hName;

        this->hHealth = 40;
        this->hStamina = 80;
    }

};

int main() {
    string hName;
    int hClass;


    cout << "Welcome to Ryan's Dungeons amp; Dragons Adventure!nn";
    cout << "Enter your Heroes namen";
    cout << "Name: ";
    cin >> hName;

    cout << hName << ", please select your classn";
    cout << "(1) The Wizardn";
    cout << "(2) The Warriorn";
    cout << "(3) The Roguen";
    cout << "(4) The Priestn";

    cout << "Class: ";
    cin >> hClass;

    switch (hClass) {
    case 1:
        Wizard _hero;
        break;
    }

    cout << _hero->GetName();


    system("PAUSE");
    return 0;
}
  

Ошибка, о которой идет речь, возникает в строке:

cout << _hero->getName();

где говорится, что _hero не определен.

Комментарии:

1. Вам нужна фабрика, которая возвращает интеллектуальный указатель вашего базового класса «CharacterClass» / Hero. Когда задано значение 1 (или что бы вы ни использовали для обозначения «Мастер»), фабрика возвращает экземпляр класса Wizard. И дайте этому базовому классу виртуальный деструктор.

2. Было бы действительно здорово, если бы C разрешил это… Это избавило бы от такой большой головной боли… Иногда строгая безопасность типов в C является проблемой. 😛

Ответ №1:

_hero определяется только в рамках этого switch оператора. Вам нужно создавать объекты в той же или более высокой области видимости, в которой вы их будете использовать.

Один из способов обойти это — определить указатель на Hero перед switch (инициализирующий на null ), а затем присвоить ему значение внутри switch . Например:

 Wizard *_hero = NULL;
switch (hClass) {
    case 1:
        _hero = new Wizard();
        break;
    }
}

if (_hero) {
    cout << _hero->GetName();
}
  

Вы также используете -> для значения класса (в отличие от указателя на единицу). Помимо проблем с областью видимости, вы, вероятно, намеревались написать _hero.GetName() . Однако внутри вашего класса он -> верен, поскольку this является указателем на ваш объект.

Комментарии:

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

2. ян, спасибо тебе! это избавило от ошибки. Я переключил его на _hero. getName и это выдало мне «Ошибка: выражение должно иметь тип класса» в _hero, поэтому я сохранил его в ->, это приемлемо или я должен изучить причину ошибки при использовании .?

3. Это приемлемо для решения, которое я предоставил, поскольку я использую тип указателя, а не тип значения.

4. -1 за предложение о динамическом распределении, но без объяснения того факта, что динамически выделяемый объект необходимо каким-то образом очистить (например, с помощью auto_ptr ).

Ответ №2:

 switch (hClass) {
    case 1:
        Wizard _hero;
        break;
} // <-- _hero is deallocated at this point

cout << _hero->GetName();
  

Область применения _hero ограничена инструкцией switch.

Комментарии:

1. Вы имеете в виду инструкцию switch.

2. Есть ли способ выполнить то, что я пытаюсь, или мне следует попробовать другой метод?

3. @Xeo — Да, вы правы. В случае сбоя в работе коммутатора он должен иметь возможность использоваться. Однако подумайте о ситуации, когда case 2 есть совпадение и в нем используется экземпляр.

Ответ №3:

Я не думаю, что это работает даже в C # … вам нужен указатель, который будет инициализирован в инструкции switch:

 Hero* _hero = 0;

switch(hClass){
  case 1: _hero = new Wizard;
  break;
}

// use _hero ...

// at the end, delete it
delete _hero;
  

Хотя сейчас вам, скорее всего, понадобится виртуальный деструктор и виртуальные функции. Ознакомьтесь с ними, это мощная функция OO. Но вы, вероятно, знаете о них из C #.

Ответ №4:

Вы сказали, что немного знаете C # и php, чего я не знаю. Я просто хочу знать, как бы это повело себя в C #.

Создание объекта внутри некоторой области видимости и использование его вне области видимости. Например: {int a;} a = 0 ;

В C это проблема.

     switch (hClass) {
    case 1:
        Wizard _hero;
        break;
    }
//At this no _hero is present. _hero is out of its scope
  

Ответ №5:

_hero Объект ограничен областью действия этого switch блока. Вероятно, вы хотите следующее:

 Hero* _hero;

switch (hClass) {
case 1:
    _hero = new Wizard();
    break;
}

cout << _hero->GetName();
  

Комментарии:

1. Когда я попробовал это, ошибка исчезает, однако, когда я пытаюсь ее отладить, я получаю сообщение об ошибке неразрешенных внешних

2. @Morgan: Ну, я понятия не имею, что это значит. Вы ввели «1» в качестве входных данных (просто чтобы убедиться)?

3. Даже не доходит до этого момента. Нажмите F5 для отладки, и она остановится с этой ошибкой. Проверю Google и посмотрю, найду ли я что-нибудь

4. @Morgan: Если вы инициализируете его равным NULL, как в Hero* _hero = NULL , устраняет ли это проблему?

5. Нет. Все та же ошибка — ошибка LNK2001: неразрешенный внешний символ «public: void __этот вызов Hero::Create(класс std::basic_string<char, структура std::char_traits<char>, класс std::allocator<char>>)» (?Создать@Hero@@UAEXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@ зппп@@@Z)