Class 私有成员 - 数组访问失败
Class private member - array accessing failed
所以我在 C++ 中有这段代码,这只是学习 C++ 的练习:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int random(int max){
srand(time(NULL));
return rand() % max;
}
class player{
public:
player(){
liv = 5;
mun = 3;
}
void Rename(char name[]){
name = name;
}
void set_group(player pl[]){
pl = pl;
}
void fire(){
if (liv > 0 and mun){
mun -= 1;
int hit = random(10);
printf("%d: ", hit);
printf("%s", pl[hit].get_name());
if (hit < 5 and pl[hit].live()){
pl[hit].hit();
printf("Player %s hit player %s!", name, pl[hit].get_name());
}
}
}
bool live(){
return liv;
}
void hit(){
liv -= 1;
}
char * get_name(){
return name;
}
private:
int liv, mun;
char name[100];
player *pl;
};
main(){
player pl[5];
char str[100];
int x;
for (x=0;x<5;x++){
sprintf(str, "%d", x + 1);
pl[x].Rename(str);
pl[x].set_group(pl);
}
pl[0].fire();
}
编译器 (TDM-GCC 4.9.2 32-bit
) 编译代码,returns 0 个警告和 0 个错误。
当我 运行 程序时,我收到消息:classes.exe has encountered a problem and needs to close. We are sorry for the inconvenience.
我调试了一下,发现第printf("%s", pl[hit].get_name());
行有问题(实际上是调试行,后面的行确实有问题,但都是一样的)。我也认为访问 pl 是个问题。
我对 C 和 C++(尤其是 C+)比较陌生,我的主要编程语言是 Python 所以不要对我的错误笑太多。
这实际上什么也没做。
void Rename(char name[]){
name = name;
}
其实相当于
void Rename(char *p){
p = p;
}
你想要
void Rename(char name[]){
strcpy(this->name, name);
}
但更好的方法是使用不冲突的名称并添加一些错误检查。
[ 编辑 ] "set_group(player pl[])" 存在同样的问题 - 感谢@Kevin 发现了这个问题。
有几项我建议您更改:
- 您不应该在每次掷出新的随机数时都设置种子。尝试多次在循环中调用随机函数,您会发现每次都得到相同的数字。
- 使用
std::vector
而不是 C 风格的数组
- 使用
std::string
而不是字符
- 如果您使用
std::cout
而不是 printf
,则您不必自己处理格式设置。
- 您的
player
构造函数没有设置名称。因此,可以创建一个不完整状态的播放器(即没有名称)
- 在构造函数中使用初始化列表更有效
- 玩家真的需要知道自己在哪个组吗?我建议更改它,因为在 atm 中,您将单个玩家的身份与他们之间的互动方式混合在一起。
- 如果玩家组只有一个玩家怎么办?您的代码无法处理这种情况。
- 玩家可以用你的代码打自己。不确定这是否是您想要的 ;)
总的来说,它可能是这样的:
#include <time.h>
#include <string>
#include <iostream>
#include <vector>
#include <cstdlib> // for rand()
void init_random(){srand(time(0));}
int random(int max){return rand() % max;}
class player{
public:
player(std::string name) : liv(5),mun(3),name(name){}
void Rename(std::string newname){name = newname;}
bool live(){return liv;}
void hit(){liv -= 1;}
void fire(){mun -= 1;}
std::string get_name(){return name;}
private:
int liv, mun;
std::string name;
};
class player_group{
public:
void addPlayer(const player& p){players.push_back(p);}
void fire(int i){
// avoid wrong input
if (i>=0 && i<players.size() && players.size()>1){
players[i].fire();
int other = i;
// avoid player hitting himself
while (other == i){other = random(players.size());}
players[other].hit();
std::cout << "Player "
<< players[i].get_name()
<< " hits player "
<< players[other].get_name()
<< std::endl;
}
}
private:
std::vector<player> players;
};
int main() {
init_random();
player_group pg;
pg.addPlayer(player("Peter"));
pg.addPlayer(player("Paul"));
pg.fire(0);
}
自 C++11 以来,出现了更好的随机生成器。如果您需要高质量的随机性,您应该使用它们而不是具有 some issues 的 rand()
。但是,在这种情况下,恕我直言 rand()
就好了。
另请注意,在我的代码中,玩家组 "owns" 玩家。我的意思是 addPlayer()
调用 push_back()
向向量添加一个副本。如果这不是您想要的,您可以考虑将 player_group
更改为包含 std::vector<player*>
以避免复制。
所以我在 C++ 中有这段代码,这只是学习 C++ 的练习:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int random(int max){
srand(time(NULL));
return rand() % max;
}
class player{
public:
player(){
liv = 5;
mun = 3;
}
void Rename(char name[]){
name = name;
}
void set_group(player pl[]){
pl = pl;
}
void fire(){
if (liv > 0 and mun){
mun -= 1;
int hit = random(10);
printf("%d: ", hit);
printf("%s", pl[hit].get_name());
if (hit < 5 and pl[hit].live()){
pl[hit].hit();
printf("Player %s hit player %s!", name, pl[hit].get_name());
}
}
}
bool live(){
return liv;
}
void hit(){
liv -= 1;
}
char * get_name(){
return name;
}
private:
int liv, mun;
char name[100];
player *pl;
};
main(){
player pl[5];
char str[100];
int x;
for (x=0;x<5;x++){
sprintf(str, "%d", x + 1);
pl[x].Rename(str);
pl[x].set_group(pl);
}
pl[0].fire();
}
编译器 (TDM-GCC 4.9.2 32-bit
) 编译代码,returns 0 个警告和 0 个错误。
当我 运行 程序时,我收到消息:classes.exe has encountered a problem and needs to close. We are sorry for the inconvenience.
我调试了一下,发现第printf("%s", pl[hit].get_name());
行有问题(实际上是调试行,后面的行确实有问题,但都是一样的)。我也认为访问 pl 是个问题。
我对 C 和 C++(尤其是 C+)比较陌生,我的主要编程语言是 Python 所以不要对我的错误笑太多。
这实际上什么也没做。
void Rename(char name[]){
name = name;
}
其实相当于
void Rename(char *p){
p = p;
}
你想要
void Rename(char name[]){
strcpy(this->name, name);
}
但更好的方法是使用不冲突的名称并添加一些错误检查。
[ 编辑 ] "set_group(player pl[])" 存在同样的问题 - 感谢@Kevin 发现了这个问题。
有几项我建议您更改:
- 您不应该在每次掷出新的随机数时都设置种子。尝试多次在循环中调用随机函数,您会发现每次都得到相同的数字。
- 使用
std::vector
而不是 C 风格的数组 - 使用
std::string
而不是字符 - 如果您使用
std::cout
而不是printf
,则您不必自己处理格式设置。 - 您的
player
构造函数没有设置名称。因此,可以创建一个不完整状态的播放器(即没有名称) - 在构造函数中使用初始化列表更有效
- 玩家真的需要知道自己在哪个组吗?我建议更改它,因为在 atm 中,您将单个玩家的身份与他们之间的互动方式混合在一起。
- 如果玩家组只有一个玩家怎么办?您的代码无法处理这种情况。
- 玩家可以用你的代码打自己。不确定这是否是您想要的 ;)
总的来说,它可能是这样的:
#include <time.h>
#include <string>
#include <iostream>
#include <vector>
#include <cstdlib> // for rand()
void init_random(){srand(time(0));}
int random(int max){return rand() % max;}
class player{
public:
player(std::string name) : liv(5),mun(3),name(name){}
void Rename(std::string newname){name = newname;}
bool live(){return liv;}
void hit(){liv -= 1;}
void fire(){mun -= 1;}
std::string get_name(){return name;}
private:
int liv, mun;
std::string name;
};
class player_group{
public:
void addPlayer(const player& p){players.push_back(p);}
void fire(int i){
// avoid wrong input
if (i>=0 && i<players.size() && players.size()>1){
players[i].fire();
int other = i;
// avoid player hitting himself
while (other == i){other = random(players.size());}
players[other].hit();
std::cout << "Player "
<< players[i].get_name()
<< " hits player "
<< players[other].get_name()
<< std::endl;
}
}
private:
std::vector<player> players;
};
int main() {
init_random();
player_group pg;
pg.addPlayer(player("Peter"));
pg.addPlayer(player("Paul"));
pg.fire(0);
}
自 C++11 以来,出现了更好的随机生成器。如果您需要高质量的随机性,您应该使用它们而不是具有 some issues 的 rand()
。但是,在这种情况下,恕我直言 rand()
就好了。
另请注意,在我的代码中,玩家组 "owns" 玩家。我的意思是 addPlayer()
调用 push_back()
向向量添加一个副本。如果这不是您想要的,您可以考虑将 player_group
更改为包含 std::vector<player*>
以避免复制。