如何在switch语句中声明全局对象

时间:2017-10-27 20:51:00

标签: c++ class object

我遇到了问题,我需要根据用户输入为类声明一个对象。问题是对象的范围被卡在switch语句中,我想知道是否有办法让它公开。

//ask the user to choose the class of the first fighter
    cout << "Welcome to the fighting arena! Would you like the first competitor to be a FIGHTER <1>, a WIZARD <2>, a ROGUE <3>, or a RANGER <4>?" << endl;
    cin >> competitor1;
    cout << "And what is the name of the competitor?" << endl;
    cin >> name1;

    //creates an object in the appropriate class and initializes it
    switch (competitor1)
    {

    case 1:
    {
        Fighter Battler1(name1);
        break;
    }

    case 2:
    {
        Wizard Battler1(name1);
        break;
    }

    case 3:
    {
        Rogue Battler1(name1);
        break;
    }
    case 4:
    {
        Ranger Battler1(name1);
        break;
    }
    default:
        cout << "Sorry please enter a valid number!" <<endl << endl;
        break;
    }

cout << Battler1.hp //this is undefined because of the scope

是的,所有内容都写在主要内容中,我知道问题是范围,只需要一种方法来解决它。

3 个答案:

答案 0 :(得分:2)

你不能像你描述的那样去做。你需要某种多态性:一个会根据它的类型改变它的行为的对象。

最简单的方法是使用变体:

using Battler = std::variant<Fighter, Wizard, Rogue, Ranger>;

auto battler1 = [&]() -> std::optional<Battler> {
    switch (competitor1)
    {
    case 1:
        return Fighter{name1};

    case 2:
        return Wizard{name1};

    case 3:
        return Rogue{name1};

    case 4:
        return Ranger{name1};

    default:
        cout <<"Sorry please enter a valid number!" << endl;
        return std::nullopt;
    }
}();

// if a valid number has been chose.
if (battler1) {
    cout << std::visit([](auto& battler) { return battler.hp; }, *battler1);
}

请注意,您需要使用最新的编译器,或使用boost::variant代替。此解决方案可能也不是最具可伸缩性的,因为在添加新的battler类型时,您需要有效地更新Battler别名。

此外,您可以通过指针和vtables使用多态。它需要对您的程序进行更多更改,但在某些情况下可能更合适:

struct Battler {
    virtual int getHp() const = 0;
    virtual ~Battler() = default;
};

struct Fighter : Battler {
    int getHp() const override {
        return hp;
    }
};

struct Wizard : Battler {
    int getHp() const override {
        return hp;
    }
};

// ... all other classes of Battler

然后,相应地改变你的情况:

std::unique_ptr<Battler> battler1;
switch (competitor1)
{
case 1:
    battler1 = std::make_unique<Fighter>(name1);
    break;

case 2:
    battler1 = std::make_unique<Wizard>(name1);
    break;

case 3:
    battler1 = std::make_unique<Rogue>(name1);
    break;

case 4:
    battler1 = std::make_unique<Ranger>(name1);
    break;
default:
    cout << "Sorry please enter a valid number!" <<endl << endl;
    break;
}

// if a valid number has been chose
if (battler1) {
    cout << battler1->getHp();
}

答案 1 :(得分:2)

我根本不会在这里使用开关盒,而是使用一系列仿函数,每个仿函数都会创建一个不同类型的战斗机并返回一个指向它们基座的指针,即

template<typename T>
std::unique_ptr<Champion> Create( ) { return std::make_unique<T>( ); }

std::function<std::unique_ptr<Champion>(void)> createFunctions [] = {
    Create<Fighter>
   ,Create<Rogue>
   ,Create<Wizard>
   ,Create<Ranger>
};

用法:

std::cin >> competitor1;
std::unique_ptr<Champion> Battler1 = createFunctions[competitor1];
std::cout << Battler1->hp;

答案 2 :(得分:0)

如果你可以使对象(Battler1)全局化,它会是什么数据类型?课程FighterWizardRogueRanger的实例?

你的问题的解决方案是这样的:创建一个父类(比方说,Character),所有其他的(Fighter ...)将继承它们:class Fighter : Character等。然后,动态创建对象:

Character *battler;

switch (...) {
case 1:
    battler = new Fighter(name);
    break;
case 2:
    battler = new Wizard(name);
    break;
}

// don't forget to free the memory when not needed anymore
delete battler;