2013-02-28 138 views
1

我已經搜索,但一直沒能得到我想要的...在函數之間傳遞結構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(); 
} 

調用上述所有函數。

但我不出來...我想引用指針沒有運氣。我需要一些幫助,在這裏,請...

回答

3

這個怎麼樣?

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

1

不要使用傳址值

使用指針,而不是通過可在函數修改變量的地址創建一個複雜數據類型的數據的額外副本。這些更改也會反映在調用者的功能中。

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

-1

我會建議返回一個指向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否則就會有內存泄漏