2017-09-27 97 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

看起来你正试图给另一个引用'OutWeapon'分配一个引用'Weapon1',它不会做你期望的。在C++中,不可能重新绑定引用。赋值引用总是导致对引用对象的赋值。 – VTT

+0

当你调用'GetWeapon()'时,你为'OutWeapon'分配内存然后通过。你真正需要的是返回一个指针。 – CinCout

回答

4

重构到

FWeaponSlot& ULoadout::GetWeapon(int32 InIndex) 

是这样做的合理的,地道,方式。 (C++不允许你重新绑定引用。)

+1

尽管如此,应该提到复制问题仍然存在,如果结果未再次分配给引用。如果目标是具有独立生命期的另一个类别的成员(即该成员可以在被指定之前存在),它必须是一个指针... – Aconcagua

+0

这不会很好地处理他的“默认”情况... – 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功能:

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! 

现在发生在getWeapon什么有效的是:

s = weapon1; 

注意s是一个对象,而不是一个参考,所以你复制u.weapon1s ...

要在特定情况下避免此问题,您需要一个指针而不是:

FWeaponSlot* s = u.getWeapon(0); 

请注意,我默默地改变了签名(只是为了方便上调用)...

u仍然是对象的所有者,并会自动清除它们被破坏的时候,所以在这个特定情况下不需要任何类型的智能指针。只要确保你不使用s指针的结束u寿命后...

0

而采取FWeaponSlot*&将解决您的问题,我建议使用,而不是普通的getter:

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

但是,你需要检查InIndex是方法中是有效的,你有没有返回值,指示的方式“没有武器”。我们将向希望在顶部是这样的的方法:

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

另一种方法是返回一个指针,并有null表示 “没有武器”:

FWeaponSlot* ULoadout::GetWeapon(int32 InIndex);