Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

flowchart

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?

like image 887
Ramin Amiri Avatar asked Jan 28 '19 14:01

Ramin Amiri


2 Answers

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.

like image 161
Kunal Puri Avatar answered Nov 14 '22 23:11

Kunal Puri


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;
}
like image 44
Spinkoo Avatar answered Nov 14 '22 23:11

Spinkoo