C++笔记:C++中的重载

重载的概念

一.函数重载

代码演示例子:


#include<iostream>
using namespace std;//函数名相同,在是每个函数的参数不相同
void output(int x) {printf("output int : %d\n", x);return ;
}void output(long long x) {printf("output long long : %llX\n", x);return ;
}void output(const char *s) {if (!s) {printf("output string : nullptr\n");return ;}printf("output string : %s\n", s);return ;
}void output(int x, int y) {printf("output double int : %d, %d\n", x, y);return ;
}
//如果调用这个函数时,没有传入参数3,也就是c
//那么c的默认值就为123,并且程序不会编译不通过
void output(int a, char b, int c = 123) {printf("output a = %d, b = %c, c = %d\n", a, b, c);return ;
}//如果这里没有第三个参数,那么就会造成编译报错
//因为没有办法通过返回值类型进行区分重载类型
//也就是没有办法区分和上面的double int进行区分
const char *output(int a, int b, char c) {printf("output a = %d, b = %d, c = %c\n", a, b, c);return "yes";
}int main() {output(3);//这里匹配的是int类型的output//在数字后面加上LL 表示这个数字是longlong类型output(3LL);//这里匹配的是longlong类型的outputoutput("hello world");//匹配参数为char *的outputoutput(3, 4);//匹配参数为两个int类型的outputoutput(3LL, 4);//近似匹配了两个int类型的output//下面这个output(NULL),他会匹配到int类型//NULL可以表示成0值//然后它也可以表示成一个地址,然后它又是0值的地址,地址有64位也就是8字节,那他也会匹配long long类型//然后还表示一个空地址,还会匹配到char *类型//output(NULL);//而在C++中 nullptr只表示空地址,这样他就会精确匹配对应的函数output(nullptr);output(12, 'p');cout << output(3, 4, 'c') << endl;return 0;
}

然后如果output(NULL)那行代码没有注释掉,那么就会出现,注释说明的情况,无法匹配造成歧义:

对于成员函数重载和普通函数的重载一样,我就不用代码进行演示了。

二.运算符重载

不能重载的运算符:

类外:

参考代码:

#include <iostream>
#include <cstdio>
using namespace std;class Point {
public :Point() : x(0), y(0), output_width(0) {}Point(int x, int y) : x(x), y(y), output_width(0) {}
private :int x, y;int output_width;//利用友元进行解决私有成员属性的访问问题friend ostream &operator<<(ostream &out, const Point &p);friend int operator*(const Point &, const Point &);friend Point operator+(const Point &, int );friend double operator*(const Point &, double );friend double operator*(double , const Point &);friend Point &operator-(Point &, int x) ;friend Point &operator-(Point &, Point &) ;friend Point &operator-(Point &, const char *) ;
};
//ostream类型就像cout的对象的类型
//加上const为了同时支持const和非const限定的对象
ostream &operator<<(ostream &out, const Point &p) {out << "("  << p.x << ", " << p.y << ")";return out; 
}int operator*(const Point &p1, const Point &p2) {return p1.x * p2.x + p1.y * p2.y;
}Point operator+(const Point &p1, int x) {Point p(p1.x + x, p1.y + x);return p;
}double operator*(const Point &p1, double x) {return p1.x * x + p1.y * x;
}double operator*(double x, const Point &p1) {//这里他调用的就是上面运算符重载的方法return p1 * x;
}Point &operator-(Point &p, int x) {p.output_width = x; return p;
}Point &operator-(Point &p1, Point &p2) {char str[100] = {0};snprintf(str, 99, "(%%%dd, %%%dd)", p1.output_width, p1.output_width);printf(str, p2.x, p2.y);return p1;
}Point &operator-(Point &p, const char *s) {printf("%s", s);return p;
}Point &operator^(Point &p1, const Point &p2) {return p1;
}Point &operator^(Point &p1, int x) {return p1;
}int main() {Point p1(5, 6), p2(3, 6), p3(6, 9), p4(10, 12);//cout他也不认识我们创建的Point类//如果要对cout进行对p1进行输出//那么我们就要对<<这个左移运算符进行重载cout << p1 << endl;//这里对运算符的重载可以不用实现和我一样的,可以通过自己的想象然后来实现//然后实现的结果和自己的想象的需要是一样的结果cout << p1 * p2 << endl;cout << p1 * 2.3 << endl;cout << 2.3 * p1 << endl;cout << p1 + 5 << endl;//实现效果//p1 - 6设置输出的位宽为6//- p2 输出p2的值,并且输入的位宽为p1的位宽//- "\n" 换行p1 - 6 - p2 - "\n";return 0;
}

练习:

        实现下面的代码:

    Point p1(5, 6), p2(3, 6), p3(6, 9), p4(-2, -4);cout << p1 << p2 << p3 << p4 << endl;//^运算符将每个类中的成员属性x,y输出到一个坐标轴中//^1时打印出这个坐标轴p1^p2^p3^p4^1;

参考代码:

#include <iostream>
#include <cstdio>
using namespace std;#define MAX_N 20class Point {
public :Point() : x(0), y(0) {}Point(int x, int y) : x(x), y(y) {}~Point() {}static void init_x_y_axis() {for (int i = 0; i < MAX_N; i++) {Point::x_y_axis[i] = new int[MAX_N + 5];}return ;}static void set_x_y_axis(int x, int y) {if (x_y_axis[x + MAX_N / 2][y + MAX_N / 2]) return ;x_y_axis[x + MAX_N / 2][y + MAX_N / 2] = 1;return ;}void output() {cout << sizeof(Point::x_y_axis[0]) << endl;cout << sizeof(Point::x_y_axis) << endl;}friend Point &operator^(Point &, Point &);friend Point &operator^(Point &, int);friend ostream &operator<<(ostream &, const Point &);
private :int x, y;//创建一个类属性//用来当作坐标轴static int **x_y_axis;
};int **Point::x_y_axis = new int*[MAX_N + 5];Point &operator^(Point &p1, Point &p2) {//将每个对象的x,y输出到坐标轴中Point::set_x_y_axis(p1.x, p1.y);Point::set_x_y_axis(p2.x, p2.y);return p1;
}Point &operator^(Point &p1, int num) {//我们要求的是^1才打印if (num != 1) return p1;for (int y = MAX_N / 2; y > -MAX_N / 2; y--) {for (int x = -MAX_N / 2; x < MAX_N / 2; x++) {!x && y && printf("%3d", y);if (!y) {printf("%3d", x);} else {if (Point::x_y_axis[x + (MAX_N / 2)][y + (MAX_N / 2)]) {printf("%3c", '*');}else if (x) printf("%3c", ' ');}}putchar(10);}return p1;
}ostream &operator<<(ostream &out, const Point &p1) {out << "p("  << p1.x << ", " << p1.y << ")" << endl;return out;
}int main() {Point::init_x_y_axis();Point p1(5, 6), p2(3, 6), p3(6, 9), p4(-2, -4);cout << p1 << p2 << p3 << p4 << endl;//^运算符将每个类中的成员属性x,y输出到一个坐标轴中//^1时打印出这个坐标轴p1^p2^p3^p4^1;return 0;
}

实现效果:

        实现结果可以和我不一样,但是一定要实现你自己的想法,C++的语法就是非常的灵活并且也非常容易出错,所以这才是C++的难处.

        注意:学习C++是学习C++的设计模式。

类内:

    对于下面的运算符,只能再类内中重载,但是不是意思是只能重载这些运算符,对于类外可以重载的运算符,类内一样也可以重载

在说类内的运算符之前说一个知识点左值右值: 

左值右值

带入代码理解:

#include<iostream>
using namespace std;#define LEFT_OR_RIGHT(expr) {\printf("expr : %s\n", #expr);\left_or_right(expr);\printf("\n");\
}void left_or_right(int &x) {printf("left value : %d\n", x);return ;
}void left_or_right(int &&x) {printf("right value : %d\n", x);return ;
}int main() {int a = 123;//a可以通过单一变量a访问//那么他就是左值LEFT_OR_RIGHT(a);//a + 1是中间产生临时的一个值//那么他无法通过单一变量进行访问到//那他就是一个右值//因为在过了下面这行代码后,我们没有办法进行通过单一变量进行访问到它LEFT_OR_RIGHT(a + 1);//任何字面量的值都是右值LEFT_OR_RIGHT(123);//这里a++你带入进去的是a的值//然后带入后,a进行了a += 1//那么在这行代码之后你无法通过单一变量去访问到之前的a值//那么它就是右值LEFT_OR_RIGHT(a++);//++a带入的是 a += 1的值//在这行代码之后,它可以通过单一变量a去访问到这个值//那他就是左值LEFT_OR_RIGHT(++a);//a += 2同理它可以通过变量a去访问到这个值LEFT_OR_RIGHT(a += 2);return 0;
}

执行结果,和我代码注释推断的结果是一样的:

然后下一个版本:

#include<iostream>
using namespace std;#define LEFT_OR_RIGHT(expr) {\printf("expr : %s\n", #expr);\left_or_right(expr);\printf("\n");\
}void left_or_right(int &&, int);void left_or_right(int &x, int flag = 1) {printf("left value : %d\n", x);if (flag) left_or_right(x, 0);return ;
}void left_or_right(int &&x, int flag = 1) {printf("right value : %d\n", x);if (flag) left_or_right(x, 0);return ;
}namespace test1 {
int main() {int a = 123;//a可以通过单一变量a访问//那么他就是左值LEFT_OR_RIGHT(a);//a + 1是中间产生临时的一个值//那么他无法通过单一变量进行访问到//那他就是一个右值//因为在过了下面这行代码后,我们没有办法进行通过单一变量进行访问到它LEFT_OR_RIGHT(a + 1);//任何字面量的值都是右值LEFT_OR_RIGHT(123);//这里a++你带入进去的是a的值//然后带入后,a进行了a += 1//那么在这行代码之后你无法通过单一变量去访问到之前的a值//那么它就是右值LEFT_OR_RIGHT(a++);//++a带入的是 a += 1的值//在这行代码之后,它可以通过单一变量a去访问到这个值//那他就是左值LEFT_OR_RIGHT(++a);//a += 2同理它可以通过变量a去访问到这个值LEFT_OR_RIGHT(a += 2);return 0;
}
}int main() {//test1::main();left_or_right(123);return 0;
}

执行结果:

为什么呢,123先调用右值引用没有问题吧,然后现在flag为1,需要再次调用left_or_right()函数,然后呢现在他的参数为x而不是123,那么在执行完成调用函数这句代码之后,我还是可以通过x进行访问到这个值,在右值引用这个函数的作用域里面这个x是持久态,我调用完成这个函数我是可以进行访问到的,所以第二次调用就会调用左值引用。

那么问题来了,我想保持当前的右值引用如何操作呢:

现在去理解move函数就是把move函数里的参数强制转换为右值,如果你想了解的更深可以自己看看move函数的原型,以及具体如何操作的。  

if (flag) left_or_right(move(x), 0);

改完这行代码后执行结果:

还有一种方式:

forward<>()函数,forward 函数通常用于完美转发,用于将参数原封不动地传递给另一个函数,保持参数的值类别不变。

if (flag) left_or_right(forward<int &&>(x), 0);

forward在这句代码的作用就是将x作为右值引用作为传入参数,但是x他还是左值引用。

但是move是将x变为了右值引用。

移动构造 

那么说完左值右值,那么对于构造函数还有一种形式,叫做移动构造:

代码演示:

#include <iostream>
#include <cassert>
#include <ctime>
using namespace std;class Array {
public :Array(int n) : n(n), arr(new int[n]) {cout << "array default constructor " << arr << endl;}Array(const Array &a) : n(a.n), arr(new int[n]) {cout << "copy array constructor " << arr << endl;for (int i = 0; i < n; i++) arr[i] = a[i];return ;}//再函数调用时,如果没有返回值优化//那么调用func()函数时,会先默认构造a,//默认构造返回值的隐匿对象,这里创建了新的空间//然后a拷贝给匿名对象//然后又将匿名拷贝给b对象,有创建了新空间//而移动构造,直接将第一次a创建的空间直接给匿名对象//匿名对象又通过移动构造将创建的空间给b对象,省去了中间创建新空间的步骤和释放空间的步骤Array(Array &&a) : n(a.n), arr(a.arr) {cout << "move constructor" << arr << endl;a.arr = nullptr;a.n = 0;return ;}//这里为什么要返回int &//因为你在访问该位置时,又可以能会将该位置进行赋值//所以需要返回int &int &operator[](int ind) const{assert(ind >= 0 && ind < n);return arr[ind];}void output(const char *frm) {for (int i = 0; i < n; i++) {printf(frm, i, arr[i]);}}~Array() {if (arr) delete[] arr;cout << "array disconstructor " << arr << endl;return ;}
private :int n;int *arr;
};Array func() {int n = 7;Array a(n);for (int i = 0; i < n; i++) {a[i] = i;}return a;
}int main() {srand(time(0));int n = 10;printf("a = ");Array a(n);for (int i = 0; i < n; i++) {a[i] = rand() % 100;}a.output("a[%d] = %d\n");Array b = func();b[0] = 999;b.output("b[%d] = %d\n");//如果对于a对象不用了,想将a对象所有的东西给c对象//那么就可以调用移动构造,使用move函数将a对象传入时变为右值Array c(move(a));c.output("c[%d] = %d\n");return 0;
}

 类内的运算符重载代码演示:
 前后++代码演示:
#include<iostream>
using namespace std;class Point {
public :Point(int x, int y) : x(x), y(y) {}Point(const Point &a) : x(a.x), y(a. y) {}//+重载, p1 + p2 就是 p1.x + p2.x, p1.y + p2.y//因为返回的是一个新的值,所以是右值,返回值类型就不是引用,也就是不是左值Point operator+(const Point &p) {//他这里是成员方法,比如它可以访问this指针Point ret(x + p.x, y + p.y);return ret;}//由于是前++,就不需要参数//前++返回的是左值,所以返回值类型也是左值//返回的对象也是本身Point &operator++() {cout << "++class" << endl;this->x += 1, this->y += 1;return *this;}//后++是一个右值,在演示左值和右值代码中有示例//那么返回的是一个新的值,所以返回值类型也是右值,而不是左值引用//参数列表中有参数,就是后++Point operator++(int) {cout << "class++" << endl;Point ret(*this);//代码设计逻辑和技巧++(*this);return ret;}friend ostream &operator<<(ostream &out, const Point &p);
private :int x, y;
};ostream &operator<<(ostream &out, const Point &p) {out << "(" << p.x << ", " << p.y << ")";return out;
}int main() {Point a(1, 2), b(3, 4);cout << "a : " << a << endl;cout << "b : " << b << endl;cout << a + b << endl;//这样去调用运算符重载的函数和上行代码执行效果一样cout << a.operator+(b) << endl;cout << "++a : " << ++a << endl;cout << "b++ : "<< b++ << endl;cout << "b : "<< b << endl;return 0;
}

=赋值运算符重载代码演示:


#include<iostream>
using namespace std;class A {
public :A() {cout << "default constructor " << this << endl;}A(const A &a) {cout << "copy constructor " << this << endl;}A(const A &&a) {cout << "move constructor " << this << endl;}//对于=重载A &operator=(const A &a) {//new关键字的原地构造//在this指针这块位置调用拷贝构造//this指针指向的就是下面的对象cnew(this) A(a);cout << "operator= " << this << endl;return *this;}A &operator=(A &&a) {new(this) A(move(a));cout << "operator= " << this << endl;return *this;}
};int main() {A a, c, d;A b = a;c = a;d = move(a);cout << "a = " << &a << endl;cout << "b = " << &b << endl;cout << "c = " << &c << endl;cout << "d = " << &d << endl;return 0;
}
[]、->、()运算符重载代码演示:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;class Array_Object {
public :int operator[](int ind) {return 2 * ind;}
};class Function_Object {
public :int operator()(int x) {return 2 * x; }
};class Point {
public :Point(int x, int y) : x(x), y(y){printf("x = %d, y = %d\n", x, y);}int x, y;
};class Point_Object {
public :Point_Object() : p(new Point(rand() % 100, rand() % 100)) {}Point *operator->() {return p; }~Point_Object() {delete p;}
private :Point *p;
};int main() {srand(time(0));Array_Object arr;Function_Object fun;Point_Object p;cout << p->x << " " << p->y << endl;for (int i = 0; i < 10; i++) {cout << "arr[" << i << "]" << arr[i] << endl;}for (int i = 0; i < 10; i++) {cout << "fun(" << i << ")" << fun(i) << endl;}return 0;
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/2471.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

php 编译安装oracel扩展

第一步安装Oracle客户端 1&#xff0c;需要下载基础包和sdk oracle客户端下载链接&#xff1a;Oracle Instant Client Downloads for Linux x86-64 (64-bit) https://www.oracle.com/database/technologies/instant-client/linux-x86-64-downloads.html 选择最新版本 versi…

11 JavaScript学习:事件

Html事件 HTML 中有很多事件可以用来与用户交互&#xff0c;以下是一些常见的 HTML 事件及其详细解释和举例&#xff1a; click 事件&#xff1a;当用户点击元素时触发。 <button onclick"myFunction()">点击我</button>dblclick 事件&#xff1a;当用…

在Jupyter notebook中添加虚拟环境

通常我们打开Jupyter notebook&#xff0c;创建一个新文件&#xff0c;只有一个Python3&#xff0c;但是我们也会想使用自己创建的虚拟环境&#xff0c;很简单仅需几部即可将自己的conda环境添加到jupyter notebook中。 1. 创建并激活conda环境&#xff08;已有可跳过&#xf…

数据结构基础:链表操作入门

数据结构基础&#xff1a;链表操作入门 数据结构基础&#xff1a;链表操作入门链表的基本概念链表的基本操作输出链表插入节点删除节点查找值 完整的链表操作示例结语 数据结构基础&#xff1a;链表操作入门 在计算机科学中&#xff0c;数据结构是组织和存储数据的方式&#x…

哪些因素影响了PCB电路板切割精度?

PCB电路板切割是电子制造过程中一个至关重要的环节&#xff0c;其精度对后续工序的质量和效率具有决定性影响。因此&#xff0c;了解影响PCB电路板切割精度的原因&#xff0c;对于提高电子产品的质量和生产效率具有重要意义。 1. PCB分板机稳定性 PCB分板机的性能直接影响到切…

docker内实现多机多卡分布式训练

docker内实现多机多卡分布式训练 1. 多台docker宿主机网络配置2. 创建overlay 网络3. 注意 1. 多台docker宿主机网络配置 https://docs.docker.com/network/overlay/ 这里需要创建overlay网络使得多台宿主机的容器可以通过网络连接 初始化swarm集群&#xff0c;并设置主节点&a…

Tensorflow2.0笔记 - BatchNormalization

本笔记记录BN层相关的代码。关于BatchNormalization&#xff0c;可以自行百度&#xff0c;或参考这里&#xff1a; 一文读懂Batch Normalization - 知乎神经网络基础系列&#xff1a; 《深度学习中常见激活函数的原理和特点》《过拟合: dropout原理和在模型中的多种应用》深度…

【JavaEE多线程】线程中断 interrupt()

系列文章目录 &#x1f308;座右铭&#x1f308;&#xff1a;人的一生这么长、你凭什么用短短的几年去衡量自己的一生&#xff01; &#x1f495;个人主页:清灵白羽 漾情天殇_计算机底层原理,深度解析C,自顶向下看Java-CSDN博客 ❤️相关文章❤️&#xff1a;清灵白羽 漾情天…

StarRocks最佳实践经验

目录 一、部署 1.1 容量规划 1.2 基础环境配置 1.3 机器配置 1.3.1 FE节点 1.3.2 BE节点 1.4 部署方案 二、建模 2.1 建表规范 2.2 模型选择 2.3 排序列和前缀索引选择 2.4 分区选择 2.5 分桶选择 2.6 字段类型 2.7 索引选择 2.7.1 Bitmap索引 2.7.2 Bloom fi…

debian8安装后无法使用博通无线网卡BCM43224,提示缺少固件

装完debian8后发现主机自带的无线网卡不能使用,并且在安装系统过程中会有提示: 您的一些硬件需要非自由固件文件才能运转。固件可以从移动介质加载。 缺失的固件文件是:brcm/brcm43xx-0.fw我没有理会,装完后发现无线网卡不能用 需要安装 broadcom-wl 查看网卡芯片型号 …

笔记本电脑耗电和发热比较厉害怎么处理

工作中会遇到有同事反馈笔记本电脑耗电和发热比较厉害&#xff0c;主要检查以下几个地方 1、CPU频率 很多人觉得是cpu使用率高就代表电脑跑得快&#xff0c;发热量就大&#xff0c;其实不是的&#xff0c;主要是看的cpu频率&#xff0c;频率越高&#xff0c;电脑发热量越大。如…

(N-151)基于微信小程序校园学生活动管理平台

开发工具&#xff1a;IDEA、微信小程序 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 前端技术&#xff1a;vue、uniapp 服务端技术&#xff1a;springbootmybatisplus 本系统分微信小程序和管理后台两部分&am…

探索开源的容器引擎--------------Docker容器操作

目录 一、Docker 容器操作 1.1容器创建 1.2查看容器的运行状态 1.3启动容器 1.4创建并启动容器 1.4.1当利用 docker run 来创建容器时&#xff0c; Docker 在后台的标准运行过程是&#xff1a; 1.4.2在后台持续运行 docker run 创建的容器 1.4.3创建容器并持续运行容器…

免费开源线上社交交友婚恋系统平台 可打包小程序 支持二开 源码交付!

婚姻是人类社会中最重要的关系之一&#xff0c;它对个人和家庭都有着深远的影响。然而&#xff0c;在现代社会的快节奏生活中&#xff0c;找到真爱变得越来越困难。在这个时候&#xff0c;婚恋产品应运而生&#xff0c;为人们提供了寻找真爱的新途径。 1.拓宽人际交流圈子 现代…

手撕netty源码(一)- NioEventLoopGroup

文章目录 前言一、NIO 与 netty二、NioEventLoopGroup 对象的创建过程2.1 创建流程图 前言 本文是手撕netty源码系列的开篇文章&#xff0c;会先介绍一下netty对NIO关键代码的封装位置&#xff0c;主要介绍 NioEventLoopGroup 对象的创建过程&#xff0c;看看new一个对象可以做…

【国产替代】航空电子通信总线航空电子通信总线产品为MIL-STD-1553和ARINC 429等协议提供原生支持

航空电子通信总线 航空电子通信总线产品为MIL-STD-1553和ARINC 429等协议提供原生支持。这些产品用于进行航空电子应用所需的开发、生产和系统测试。 PXIe&#xff0c;2通道PXI ARINC-664接口模块 AIM ARINC-664具有板载处理器&#xff0c;可自动处理所有与协议相关的活动&…

界面组件DevExpress Blazor UI v23.2 - 支持.NET 8、全新的项目模版

DevExpress Blazor UI组件使用了C#为Blazor Server和Blazor WebAssembly创建高影响力的用户体验&#xff0c;这个UI自建库提供了一套全面的原生Blazor UI组件&#xff08;包括Pivot Grid、调度程序、图表、数据编辑器和报表等&#xff09;。 DevExpress Blazor控件目前已经升级…

(五)AB测试及两个案例 学习简要笔记 #统计学 #CDA学习打卡

目录 一. AB测试简介 1&#xff09;假设检验的一般步骤 2&#xff09;基于假设检验的AB测试步骤 二. 案例1&#xff1a;使用基于均值的假设检验进行AB测试 1&#xff09;原始数据 2&#xff09;提出原假设H0和备择假设H1 3&#xff09;使用均值之差的t检验&#xff0c;计…

AI视频改字个性化祝福豪车装X系统uniapp前端开源源码下载

装X系统源码简介 创意无限&#xff01;AI视频改字祝福&#xff0c;豪车装X系统源码开源&#xff0c;打造个性化祝福视频不再难&#xff01; 想要为你的朋友或家人送上一份特别的祝福&#xff0c;让他们感受到你的真诚与关怀吗&#xff1f;现在&#xff0c; 通过开源的AI视频…

【深度学习】yolo-World,数据标注,zeroshot,目标检测

仓库&#xff1a;https://github.com/AILab-CVC/YOLO-World 下载权重&#xff1a; 仓库下载和环境设置 下载仓库&#xff1a;使用以下命令从 GitHub 上克隆仓库&#xff1a; git clone --recursive https://github.com/AILab-CVC/YOLO-World.git创建并激活环境&#xff1a…