#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)