Есть ли способ объявить объекты в условном выражении? - PullRequest
0 голосов
/ 28 января 2019

flowchart

У меня проблемы с выяснением, как правильно создать объект в зависимости от выбора пользователя.

В программе я спрашиваю пользователя, к какому классу он хочет принадлежать - рыцарь или волшебник.Я использую ввод «1» или «2» для представления «Рыцарь и волшебник».

Я сделал оператор переключения, и в случае 1 я объявил объект «Рыцарь» и то же самое для мастера.

Мне нужно использовать эти объекты вне оператора switch, но я не могу.Я попытался создать объект по умолчанию, сделав Player Player;но поскольку у класса Player есть чисто виртуальная функция, я тоже не могу этого сделать.

Как мне сделать это эффективно?

Это то, что у меня пока есть:

int main()
{
std::string plyrName;
int input;
bool foo = false;

std::cout << "What is your name?\n";
std::cin >> plyrName;
std::cin.ignore(1000, '\n');

std::cout << "\nWelcome, " << plyrName << ". What class would you like to be?\n";
std::cout << "1. Knight.\n2. Wizard.\n";
std::cin >> input;

while (input != 1 && input != 2)
{
    if (foo == true)
        std::cout << "Please enter 1 for Knight and 2 for Wizard.\n";
    if (!(std::cin >> input))
    {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "\n";
        std::cout << "Only integers are allowed.\n";
    }
    else
        std::cout << "\n";
    foo = true;
}

switch (input)
{
case 1:
{
    Wizard player;
    break;
}
case 2:
{
    Knight player;
    break;
}
}


std::cout << "\nHere is your player information summary.\n";
std::cout << player.classType();

system("pause");
return 0;
}

Мне нужно получить доступ к объекту player после того, как is был создан, потому что я хочу вывести пользователю, какой класс он выбрал.Классы Рыцаря и Волшебника имеют функцию для вывода этого.

РЕДАКТИРОВАТЬ: У меня есть дополнительный вопрос.На диаграмме Knight & Wizard имеет статическую переменную «специальное имя атаки».Как я могу получить доступ к этой переменной в основной функции?Решение использования unique_ptr означает, что указатель будет указывать на базовый класс Player, таким образом, не разрешая доступ к членам производного класса, таким как статическая переменная «имя специальной атаки».У меня есть недостаток в моем дизайне?

Ответы [ 3 ]

0 голосов
/ 28 января 2019

В вашем случае, потому что вы хотите достичь полиморфизма, вам следует обратиться за указателями и ссылками.Зачем?Я очень рекомендую этот красивый ответ. Почему полиморфизм не работает без указателей / ссылок?

Итак, стоит ли использовать необработанный указатель, что-то вроде Player *?

Почти во всех сценариях,Вы никогда не должны использовать необработанные указатели, особенно когда это указывает на динамическую память.Просто потому, что любая программная ошибка или исключение может привести к пропуску delete.

Поэтому я настоятельно рекомендую вам использовать интеллектуальные указатели, представленные в C ++ 11, такие как unique_ptr и shared_ptr, которыеследуйте шаблону RAII и гарантируйте деинициализацию.

Вот пример использования unique_ptr в вашем случае.

#include <memory>

using PlayerPtr = std::unique_ptr<Player>;
using KnightPtr = std::unique_ptr<Knight>;
using WizardPtr = std::unique_ptr<Wizard>;

int main()
{
    ...
    PlayerPtr playerPtr = nullptr;

    switch (input) {
        case 1: {
             playerPtr = KnightPtr(new Knight);
        }
        break;

        case 2: {
             playerPtr = WizardPtr(new Wizard);
        }
        break;
    }

    // use playerPtr outside.
}

Редактировать:

Как справедливо указано HTNW , вы должны перейти на std::make_unique вместо использования new.Но помните, это концепция C ++ 14.Для этого у вас должна быть поддержка компилятора.

0 голосов
/ 28 января 2019

если вы создадите свою переменную внутри области видимости переключателя, она будет удалена, как только вы выйдете из этой области, ведущей вас к UB, так что вы объявите ее как указатель, чтобы она могла пережить условный оператор, т.е. вы объявите ее как базовуюуказатель класса перед & вы даете его туда, куда он указывает внутри условного оператора

#include<memory>
int main()
{
std::string plyrName;
int input;
bool foo = false;
//create your player ptr
std::unique_ptr<Game_Object> player;
std::cout << "What is your name?\n";
std::cin >> plyrName;
std::cin.ignore(1000, '\n');

std::cout << "\nWelcome, " << plyrName << ". What class would you like to be?\n";
std::cout << "1. Knight.\n2. Wizard.\n";
std::cin >> input;

while (input != 1 && input != 2)
{
    if (foo == true)
        std::cout << "Please enter 1 for Knight and 2 for Wizard.\n";
    if (!(std::cin >> input))
    {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cout << "\n";
        std::cout << "Only integers are allowed.\n";
    }
    else
        std::cout << "\n";
    foo = true;
}

switch (input)
{
case 1:
{   // initialize it  and it would work perfectly as you intend
    player = std::make_unique<WIZARD>();
    break;
}
case 2:
{   //****
    player = std::make_unique<KNIGHT>();
    break;
}
}


std::cout << "\nHere is your player information summary.\n";
std::cout << player->classType();

system("pause");
return 0;
}
0 голосов
/ 28 января 2019

Кто-то исправит меня, если я ошибаюсь, но объекты действительны только в той области, в которой они созданы, поэтому, как только вы выйдете из этого оператора switch, эти объекты больше не будут доступны.

Вы должны объявить ИГРУОбъект класса OBJECT вне оператора switch и затем создайте мастера или рыцаря (так как оба класса наследуют объект GAME OBJECT).

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