2017-10-27 4 views
0

ユーザー入力に基づいてクラスのオブジェクトを宣言する必要があるという問題があります。問題は、switch文にオブジェクトのスコープが詰まっていることです。公開する方法があるのか​​どうか疑問に思っていました。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 

はいすべてが主な機能の内側に書かれていますが、私は問題は範囲であり、それを回避する方法が必要であることを知っています。

+0

使用ブール値は、trueに1を設定し、その後、あなたはあなたが高いスコープレンジャー* rでのポインタを宣言することができ – Tyler

+8

で真であるものを宣言する。その後、スイッチでrインスタントirate =新しいレンジャー; rの代わりにr->を実行する必要があります。 – StoryTeller

+0

多型を必要とする正しいスコープ –

答えて

0

オブジェクト(Battler1)をグローバルにすることができれば、どんなデータ型ですか?クラスFighterのインスタンス、WizardRogueまたはRanger

あなたの問題を解決するには、このです:動的オブジェクトを作成し、その後、class Fighter : Characterなどと::

他のすべて( 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; 
+3

No unique_ptr make me * very * sad –

2

説明したようにすることはできません。ある種の多形性が必要です。型に応じて動作を変更するオブジェクトです。

それを行うための最も簡単な方法は、バリアントを使用することです:あなたは日付コンパイラ、またはその代わりにboost::variantを使用してまで必要

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

注意を。新しいバトラータイプを追加するときに、Battlerエイリアスを効果的に更新する必要があるため、このソリューションは最もスケーラビリティが高いとは限りません。


また、ポインターとvtableで多態性を使用することもできます。それはあなたのプログラムに多くの変更を必要とするが、いくつかのケースでは、より適切な場合があります:

その後
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(); 
} 
+0

あなたに何度も何度もご迷惑をかけて申し訳ありませんが、デフォルトのケースではreturn文がありません。そこにはUBが対処されるべきです。 – StoryTeller

+0

@StoryTellerそれは最高ではないかもしれませんが、私は今例外を選択しました。私はあなたに良い推薦を持っている、私は私の答えを編集して幸せになります。ありがとう –

+0

Mmm ..あなたの好みによって異なります。たぶん 'std :: monostate'を安全な「デフォルト」として使うのでしょうか? – StoryTeller

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; 
+0

滑らかで十分に保護されていますが、この場合はポインタが必要になることがあります。自動変数を作成して返すことができますが、コンパイラが[返却時にelide(http://en.cppreference.com/w/cpp/language/copy_elision)]に十分スマートでない場合(ただし、C++でelisionが必須であるとは思いますが) +17)、あなたはそれを「移動」することができます。 – user4581301

関連する問題