简体   繁体   中英

Is there a way to declare objects within a conditional statement?

流程图

I'm having trouble figuring out how to properly create an object depending on the user's choice.

In the program, I ask the user which they class they want to be--Knight or Wizard. I take input '1' or '2' to represent Knight and Wizard.

I made a switch statement, and within case 1, I declared an object Knight, and the same for Wizard.

I need to use these objects outside of the switch statement, but I can't. I tried to make a 'default' object by making 'Player player;' but because the Player class has a pure virtual function, I can't do that either.

How do I do this effectively?

This is what I have so far:

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;
}

I need to access the player object after is has been created, because I want to output to the user which class they selected. Both Knight and Wizard classes have a function to output this.

EDIT: I have a follow up question. In the diagram, Knight & Wizard have a static variable 'special attack name'. How can I access this variable in the main function? The solution of using unique_ptr means that the pointer will point to the base class Player, thus not allowing access to the derived class members such as the static variable 'special attack name'. Do I have a flaw in my design?

In your case, because you want to accomplish polymorphism, you should go for pointers and references. Why? I would highly recommend this beautiful answer. Why doesn't polymorphism work without pointers/references?

So, should you go for a raw pointer, something like Player * ?

In almost all scenarios, you should never ever go for raw pointers and especially, when it points to dynamic memory. Simply because any programming error or an exception might lead to delete getting skipped.

Therefore, I would highly recommend you to go for smart pointers introduced in C++11 like unique_ptr and shared_ptr which follow RAII pattern and guarantee deinitialization.

Here is an example of usage of unique_ptr in your case.

#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.
}

Edit:

As rightly pointed out by HTNW , you must go for std::make_unique instead of using new . But remember, that is a C++14 concept. You must have compiler support for it.

if you create your variable inside the switch case scope it will get deleted as soon as you leave that scope leading you to UB so you declare it as a pointer so it can outlive the conditional statement ie : you declare it as the base class pointer before & you give it to where it points inside conditional statement

#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;
}

Someone correct me if I'm wrong, but objects are only valid within the scope they are created so once you are out of that switch statement those objects are not accessible anymore.

You should declare a GAME OBJECT class object outside the switch statement and then create either the wizard or the knight (as both classes inherit GAME OBJECT).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM