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>等。具体依赖关系取决于您的操作系统和编译环境。

posted @ 2024-04-09 21:10  FBshark  阅读(13)  评论(0编辑  收藏  举报