2017-09-27 12 views
0

何らかの理由で、この参照パラメータがコピーを返しています。したがって、OutWeaponをインデックス0に変更すると、Weapon1には影響しません。私はこれを間違っているのですか?コピーを返す参照パラメータ

class ULoadout 
{ 
public: 
    ULoadout(); 

    FWeaponSlot Weapon1; 
    FWeaponSlot Weapon2; 
    FWeaponSlot Weapon3; 
    FWeaponSlot Weapon4; 

    FSkillSlot Skill1; 
    FSkillSlot Skill2; 
    FSkillSlot Skill3; 
    FSkillSlot Skill4; 

    void GetWeapon(int32 InIndex, FWeaponSlot& OutWeapon); 
    void GetSkill(int32 InIndex, FSkillSlot& OutSkill); 
}; 

void ULoadout::GetWeapon(int32 InIndex, FWeaponSlot& OutWeapon) 
{ 
    switch (InIndex) 
    { 
    case 0: 
     OutWeapon = Weapon1; 
     break; 

    case 1: 
     OutWeapon = Weapon2; 
     break; 

    case 2: 
     OutWeapon = Weapon3; 
     break; 

    case 3: 
     OutWeapon = Weapon4; 
     break; 

    default: 
     break; 
    } 
} 
+0

なぜ 'Skill2'など公開されていませんか?なぜあなたは配列を使用していませんか? –

+2

参照 'Weapon1'を別の参照' OutWeapon'に割り当てようとしているようですが、それはあなたが期待することをしません。 C++では、参照を再バインドすることはできません。参照への代入は、常に参照されるオブジェクトへの代入を引き起こします。 – VTT

+0

'GetWeapon()'を呼び出すと、 'OutWeapon'のためにメモリを割り当ててから渡します。本当に必要なのは、ポインタを返すことです。 – CinCout

答えて

4

リファクタリング

FWeaponSlot& ULoadout::GetWeapon(int32 InIndex) 

には、これを行うための賢明な、と慣用的、方法です。 (C++を使用して、参照を再バインドはできません。)

+1

結果が参照に再度割り当てられていない場合は、コピーの問題が残っていることに注意してください。ターゲットが独立した生涯を持つ別のクラスのメンバ(つまり、メンバがassignedされる前に存在する可能性がある)のメンバであれば、ポインタでなければなりません... – Aconcagua

+0

これは 'default'のケースをうまく処理しません。 – Sean

+0

@Sean :私はその場合の例外を排除する傾向があります。 – Bathsheba

0

私はこれを正しく理解していれば、参照パラメータは、それが参照するTEオブジェクトを変更するために使用することができますが、別のオブジェクトに対する呼び出し側にrefernceを割り当てることがありません。このためには、ポインタが必要であり、これは以下のように行うことができる。

void ULoadout::GetWeapon(int32 InIndex, FWeaponSlot*& OutWeapon) 
{ 
    switch (InIndex) 
    { 
    case 0: 
     OutWeapon = &Weapon1; 
     break; 
    case 1: 
     OutWeapon = &Weapon2; 
     break; 
    case 2: 
     OutWeapon = &Weapon3; 
     break; 
    case 3: 
     OutWeapon = &Weapon4; 
     break; 
    default: 
     break; 
    } 
} 

発信者は、交換するオブジェクトのアドレスも指定する必要があります。しかし、目的のオブジェクトへの参照を返すか、単純に配列インデックスを使用するなどの別の解決策が理解しやすくなるかもしれません。

0

あなたがgetWeapon関数を呼び出す方法を考えてみましょう:今効果的getWeaponに何が起こる

ULoadout u; // where ever you got it from... 

FWeaponSlot s; // you need a true object!!! 
u.getWeapon(0, s); // now you pass the true object in as reference! 

は次のとおりです。

s = weapon1; 

sがオブジェクトではなく、参照ですので、あなたにu.weapon1をコピーすることに注意してくださいs ...

特定のケースでこの問題を回避するには、ポインタが必要です代わりに:

FWeaponSlot* s = u.getWeapon(0); 

私は黙って(単に呼び出すの便宜のために)署名を変更したことに注意してください...

uは、オブジェクトの所有者のままで、破壊されたときに自動的にクリーンアップされますので、そこにありますこの特定のケースでスマートポインタの任意の種類の必要はありません。ただ... uの寿命が終わった後、あなたがsポインタを使用していないことを確認してください

0

はあなたの問題を解決するだろうFWeaponSlot*&を取るのに対し、私が代わりに通常のゲッターを使用することをお勧め:あなたが参照を使用して設定している場合

class ULoadout 
{ 
    FWeaponSlot weapons[4]; 
    FSkillSlot skills[4]; 
public: 
    ULoadout(); 

    const FWeaponSlot& GetWeapon(int32 index) const { return weapons[index]; } 
    FWeaponSlot& GetWeapon(int32 index) { return weapons[index]; } 
    const FSkillSlot& GetSkill(int32 index) const { return skills[index]; } 
    FSkillSlot& GetSkill(int32 index) { return skills[index]; } 
}; 
0

は、メソッドを変更します:

FWeaponSlot& ULoadout::GetWeapon(int32 InIndex); 

しかし、あなたは「何の武器は」一番上にこのような何かをしたいん.You'llを示す値を返す方法がないようInIndexは、メソッド内で有効であることを確認する必要があります方法の:

if(InIndex > 3) throw std::out_of_range("invalid weapon index"); 

他の代替は、ポインタを返すことです、そしてnull示す "何の武器" している:

FWeaponSlot* ULoadout::GetWeapon(int32 InIndex); 
関連する問題