C++自定义贪吃蛇Snake类一系列问题的解决
1. 类中==运算函数相关
在list对象使用 remove() 方法删去其中的成员的时候,会出现这方面的报错。
1-1. 编译报错 no match for ‘operator==
错误解释:
这个编译错误表明编译器在尝试使用==
操作符比较两个对象时找不到匹配的操作符函数。在C++中,如果你尝试比较两个自定义类型的对象,且没有为这些对象定义==
操作符,编译器将无法进行比较,从而导致这个错误。
解决方法:
1. 如果你在比较的对象是内置类型(如int、float等),确保没有错误地重载了==
操作符,如果有,移除自定义的操作符重载。
2. 如果你在自定义类型中使用了std::list
,并尝试比较其中的元素,确保你的自定义类型重载了==
操作符。你可以在你的类定义中添加如下函数
bool operator==(const YourClass& lhs, const YourClass& rhs) {
// 实现比较逻辑
}
1-2. 编译报错:bool operator== too many parameters for this operator function
这个错误信息表明你正在尝试为operator==
定义一个接收了错误数量的参数的函数。
operator==
是C++中的一个二元比较运算符,它需要两个参数来进行比较。通常情况下,这个运算符被重载为类的成员函数或者被重载为两个对象(或指向对象的指针)的非成员函数。
如果你在定义operator==
作为非成员函数,你需要提供两个参数。如果你在定义它作为成员函数,它通常只需要一个参数(另一个隐式的通过this
传递),再加上一个返回类型为bool
的值。
解决这个错误,你需要检查你的operator==
定义,确保它有正确数量的参数。
例如,如果你有一个Point
类,你可能会这样定义operator==
:
class Point {
public:
int x, y;
// 非成员函数版本
friend bool operator==(const Point& lhs, const Point& rhs) {
return lhs.x == rhs.x && lhs.y == rhs.y;
}
// 成员函数版本
bool operator==(const Point& other) const {
return x == other.x && y == other.y;
}
};
2. C++中复制值与引用的区别
2-1.调试:蛇头坐标一直不改变
问题说明:C++使用 foreach写法,值不改变问题
以下是错误的蛇运动线程:
std::list<Snake> test_snake_list;
void* snake_move_thread1(void* arg)
{
while(1)
{
for(Snake temp_snake:test_snake_list)//经测试,坐标没有变化
{
temp_snake.snake_move();
printf("head's pos[%d, %d]\t snake's len=%d\t", temp_snake.get_snake_head().x, temp_snake.get_snake_head().y, temp_snake.get_snake_len());
printf("tail's pos[%d, %d]\n", temp_snake.get_snake_total().back().x, temp_snake.get_snake_total().back().y);
}
sleep(2);//处理完所有蛇的数据之后,延时一段时间
}
}
但是蛇头、尾的坐标一直不变
最终解答:
在C++中,foreach
循环通常是通过范围for
循环实现的,这种循环不会直接修改容器内的值,但如果需要修改值,可以使用引用来达到目的。
例如,如果你有一个std::vector
并且想要遍历并修改其值,你可以这样做:
#include <iostream>
#include <vector>
int main() {
std::vector<int> nums = {1, 2, 3, 4, 5};
// 使用范围for循环并通过引用修改值
for (int &num : nums) {
num *= 2; // 将每个值翻倍
}
// 打印修改后的vector
for (const int &num : nums) {
std::cout << num << " ";
}
return 0;
}
在这个例子中,for (int &num : nums)
这行代码中的&
符号意味着num
是对nums
中元素的引用,这样我们就可以直接修改num
来改变nums
中对应的元素值。
输出将会是2 4 6 8 10
,这是因为每个数都被翻倍了。如果你不希望修改值,可以去掉&
来创建值的副本,这样原始的容器值就不会被改变。
另外,在 Java 中,也有类似的特性:
2-2 调试:snake_list 中蛇的方向不变
问题说明:C++/STL_中的push_back方法与复制数据 + 对象初始化复制的问题 的问题
在push_back中完成的是值拷贝,而不仅仅是地址的复制。
简而言之:放入list的对象与对象本身已经没关系了。如果将一个 a 放入 list 中,再去修改 a 的值,则 list 中对应的 a 的值不会发生改变。
#include <vector>
#include <iostream>
using namespace std;
typedef struct point{
int x;
int y;
}Point;
ostream& operator<<(ostream& output, const Point &a)
{
return output << a.x <<" "<< a.y;
}
int main(){
Point * a = new Point;
vector<Point> PointList;
a->x = 3;
a->y = 4;
PointList.push_back(*a);
a->x = 4;
a->y = 4;
PointList.push_back(*a);
a->x = 5;
a->y = 4;
PointList.push_back(*a);
delete a;
for (vector<Point>::iterator i = PointList.begin(); i != PointList.end(); i++){
cout << (*i)<< endl;
}
return 0;
}
解决办法:
方案1:成员改为指针,但是改动量太大了,不行。
方案2:在list 中一个一个搜索吧。
与上面的 push_back() 很相似,当初始化一个对象的时候,进行的也是复制,而不是地址的传递。(新对象已和原对象无关)
/*
*@func:设置当前蛇的头的方向
*/
void Snake::set_snake_head_dir(SnakeDir dir)
{
//下面是错误的代码,因为进行的是复制初始化,是全新的一个对象
//SnakeNode head = get_snake_head();//执行的是复制操作,这个新建的head相当于与原来的head无关。
//下面是正确的代码,即使是复制初始化,但是复制的是引用
SnakeNode &head = get_snake_head();//改成引用就可以了
head.dir = dir;
}
其他错误:
x1. struct sockaddr_in 未定义
在C和C++中,sockaddr_in结构体用于表示Internet地址(IP地址和端口号)的信息。它的声明可以在网络编程相关的头文件<netinet/in.h>中找到。该头文件中还包含其他与网络编程相关的结构体和函数声明。
要使用sockaddr_in结构体,在代码中需要包含以下头文件:
#include <netinet/in .h>
请注意,在使用sockaddr_in结构体之前,可能还需要包含其他必要的系统头文件,如<sys/socket.h>等。具体依赖关系取决于您的操作系统和编译环境。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2019-04-09 《Practical Vim》第八章:利用动作命令在文档中移动
2019-04-09 《SQL 基础教程》第二章:查询基础