在函数之间传递结构C++

问题描述:

我已经搜索,但一直没能得到我想要的...在函数之间传递结构C++

我正在做一个小游戏。我得到了这个包含玩家详细信息的struct

struct Player 
{ 
    string name; 
    int level; 
    int exp; 
    int hp; // life 
    int mp; // mana 
    int shield; 
}; 

当在菜单中,用户选择开始新游戏,它进入这个函数:

int StartNewPlayer(string name) 
    { 
     Player player; 

     player.name = name; 
     player.level = 1; 
     player.exp = 0; 
     player.hp = 20; 
     player.mp = 5; 
     player.shield = 0; 

     *pass/return the struct here* 
    } 

然后,我有一个打印游戏板的功能,并在那里我应该来自新的球员结构使用的数据,例如:

void game_board() 
{ 
    cout << "Hello!" << player.name; 

    (...) 
} 

最后,在某处main我:

int main() 
{ 
    StartNewPlayer(new_game()); 
    game_board(); 
} 

调用上述所有函数。

但我不出来...我想引用指针没有运气。我需要一些帮助,在这里,请...

这个怎么样?

Player StartNewPlayer(string name) 
{ 
    Player player; 

    player.name = name; 
    player.level = 1; 
    player.exp = 0; 
    player.hp = 20; 
    player.mp = 5; 
    player.shield = 0; 

    return player; 
} 

void game_board(Player player) 
{ 
    cout << "Hello!" << player.name; 

    (...) 
} 

int main() 
{ 
    Player player = StartNewPlayer(new_game()); 
    game_board(player); 
} 
+0

我得到这个错误编译'错误C2360:初始化'player'被'case'标签跳过。是因为'Player player = StartNewPlayer(new_game()); game_board(播放器);'在开关中? – 2013-02-28 19:59:21

+2

@HenriqueFerrolho发布'switch'代码会很有帮助。一种解决方案是用大括号包围案例,就像这样:case 0:{Player player = ...; } break;' – Pubby 2013-02-28 20:01:12

+0

ALRIGHT! :D最后!那就是诀窍!你能解释为什么吗?我想理解...另外,我有一个疑问,在这个函数中:'Player StartNewPlayer(string name)'''Player是什么意思?是返回类型?有点像int? – 2013-02-28 20:04:21

不要使用传址值

使用指针,而不是通过可在函数修改变量的地址创建一个复杂数据类型的数据的额外副本。这些更改也会反映在调用者的功能中。

void StartNewPlayer(string name, Player *player) 
{ 
    player->name = name; 
    player->level = 1; 
    player->exp = 0; 
    player->hp = 20; 
    player->mp = 5; 
    player->shield = 0; 
} 

void game_board(Player* player) 
{ 
    cout << "Hello!" << player->name; 

    (...) 
} 

int main() 
{ 
    Player player; 
    StartNewPlayer(new_game(), &player); 
    game_board(&player); 
} 

使用传递通过引用备选:

如果你引用的粉丝,(这仅仅是一个聪明的编译器把戏,利用指针的内部再次):

void StartNewPlayer(string name, Player& player) 
{ 
    player.name = name; 
    player.level = 1; 
    player.exp = 0; 
    player.hp = 20; 
    player.mp = 5; 
    player.shield = 0; 
} 

void game_board(Player& player) 
{ 
    cout << "Hello!" << player.name; 

    (...) 
} 

int main() 
{ 
    Player player; 
    StartNewPlayer(new_game(), player); 
    game_board(player); 
} 
+0

+1为避免复制构造函数的详细信息,-1表示引用只是隐藏指针的编译器技巧。 – Donnie 2013-02-28 20:35:28

+0

@Donnie - 你能解释一下你可以使用指针无法实现的引用吗? (注意:相反,我知道引用与指针相比有其局限性)如果你能向我证明,与指针相比,引用会生成一个不同的汇编代码,我将把我的声明记下来。 – Tuxdude 2013-02-28 20:39:50

+0

@Tuxdude事实上,你可以用引用来完成任何事情,你可以用指针来做所有事情,就像你可以用C完成所有你可以用C++所做的一样。但是C++具有一定的防错和易读性等优点。 – Alan 2013-02-28 20:50:41

我会建议返回一个指向Player结构的指针。如果你现在正在返回一个“引用”,它会调用Player的拷贝构造函数,这会导致更多的复杂性。

通常情况下,在StartNewPlayer(...)结束时,您声明的播放器将停止存在,因为对象范围将会结束,因此当您将其返回时,C++编译器会得到您要保留的对象活着,并将无形地为您创建一份副本。如果你返回一个指针,你真的会返回你在函数中分配的对象。

假设你有一个指针在您的播放器的结构,如

struct Player 
{ 
    int level; 
    char* name; //lets assume you did it like that 
} 

当你返回播放机,整型将被复制,但字符*不会。 ints很容易处理,而char *需要各种棘手的功能,如strlenstrncpy。您的Player结构变得越复杂,使用默认的拷贝构造函数就会遇到的问题越多。

另一种解决方案是为Player结构自己声明一个拷贝构造函数(实际上,你可以使用类,因为它们大多可以在C++中互换)。

Player(const Player& p) 
{ 
    name = p.name; 
    level = p.level; 
    // and so forth 
} 

所以我会用

Player* StartNewPlayer(std::string name) 
{ 
    Player* player = new Player(); 
    player->name = name; 
    player->level = 1; 
    // snip 
    return player; 
} 

在你的程序结束后,一定要delete player否则就会有内存泄漏