第九十九天学习记录:C++核心:类和对象Ⅴ(五星重要)友元运算符重载

news2024/11/16 13:02:29

友元

在程序里,有些私有属性也能让类外特殊的一些函数或者类进行访问,就需要用到友元的技术
友元的目的就是让一个函数或者类访问另一个类中私有成员
友元的关键字为frirend
友元的三种实现
1、全局函数做友元

#include<iostream>
using namespace std;
#include<string>

class MyHome
{
	//goodBoy全局函数是MyHome的好朋友,可以访问MyHome中私有成员
	friend void goodBoy(MyHome *myhome);

public:
	MyHome()
	{
		m_SittingRoom = "客厅";
		m_BedRoom = "卧室";
	}
	string m_SittingRoom;//客厅
private:
	string m_BedRoom;//卧室
};

//全局函数
void goodBoy(MyHome *myhome)
{
	cout << "好朋友全局函数正在访问" << myhome->m_SittingRoom << endl;
	cout << "好朋友全局函数正在访问" << myhome->m_BedRoom << endl;
}

void test01()
{
	MyHome myhome;
	goodBoy(&myhome); 
}

int main()
{
	test01();
	return 0;
}

在这里插入图片描述

2、类做友元

#include<iostream>
using namespace std;
#include<string>

//类做友元
class AWei
{
	//JieGe是AWei的好朋友,可以访问AWei中私有的成员
	friend class JieGe;
public:
	AWei();
	string m_SittingRoom;//客厅
private:
	string m_BedRoom;//卧室
};

class JieGe
{
public:
	JieGe();
	void visit();//参观函数,访问AWei中的属性
	AWei* awei;
};

//类外写成员函数
AWei::AWei() 
{
	m_SittingRoom = "客厅";
	m_BedRoom = "卧室";
}

JieGe::JieGe()
{
	//创建一个AWei对象
	awei = new AWei;
}

void JieGe::visit()
{
	cout << "JieGe正在访问" << awei->m_SittingRoom << endl;
	cout << "JieGe正在访问" << awei->m_BedRoom << endl;
}

void test01()
{
	JieGe gg;
	gg.visit();
}

int main()
{
	test01();
	return 0;
}

在这里插入图片描述

3、成员函数做友元

#include<iostream>
using namespace std;
#include<string>

class AWei;

class JieGe
{
public:
	JieGe();
	void visit();//让visit函数可以访问AWei中私有成员
	void visit2();//让visit函数不可以访问AWei中私有成员
private:
	AWei* awei;
};

class AWei
{
	//告诉编译器JieGe类下的visit成员函数作为本类的好朋友,可以访问私有成员
	friend void JieGe::visit();

public:
	AWei();
	string m_SittingRoom;//客厅
private:
	string m_BedRoom;//卧室
};

//类外写成员函数
AWei::AWei()
{
	m_SittingRoom = "客厅";
	m_BedRoom = "卧室";
}

JieGe::JieGe()
{
	//创建一个AWei对象
	awei = new AWei;
}

void JieGe::visit()
{
	cout << "visit正在访问" << awei->m_SittingRoom << endl;
	cout << "visit正在访问" << awei->m_BedRoom << endl;
}

void JieGe::visit2()
{
	cout << "visit2正在访问" << awei->m_SittingRoom << endl;
	//cout << "visit2正在访问" << awei->m_BedRoom << endl;//无法访问AWei私有
}

void test01()
{
	JieGe gg;
	gg.visit();
	gg.visit2();
}

int main()
{
	test01();
	return 0;
}

在这里插入图片描述

运算符重载

运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型

加号运算符重载

作用:实现两个自定义数据类型相加的运算

#include<iostream>
using namespace std;

//加号运算符重载
//1、成员函数重载+号

class Person
{
public:
	int m_A;
	int m_B;
	Person()
	{
		cout << "Person的构造构造函数调用" << endl;
	}
	Person(const Person &p)
	{
		m_A = p.m_A;
		m_B = p.m_B;
		cout << "Person的拷贝构造函数调用" << endl;
	}
	//Person operator+(Person &p)
	//{
	//	Person tmp;
	//	tmp.m_A = this->m_A + p.m_A;
	//	tmp.m_B = this->m_B + p.m_B;
	//	return tmp;
	//}
};

//2、全局函数重载+号

Person operator+(Person &p1, Person &p2)
{
	Person tmp;
	tmp.m_A = p1.m_A + p2.m_A;
	tmp.m_B = p1.m_B + p2.m_B;
	return tmp;
}

//函数重载的版本
Person operator+(Person &p1, int num)
{
	Person tmp;
	tmp.m_A = p1.m_A + num;
	tmp.m_B = p1.m_B + num;
	return tmp;
}

int main()
{
	Person p1;
	p1.m_A = 10;
	p1.m_B = 10;
	Person p2;
	p2.m_A = 10;
	p2.m_B = 10;
	//成员函数重载本质调用
	//Person p3 = p1.operator+(p2);
	//全局函数重载本质调用
	//Person p3 = operator+(p1, p2);
	Person p3 = p1+p2;
	cout << "p3.m_A==" << p3.m_A << endl;
	cout << "p3.m_B==" << p3.m_B << endl;
	Person p4 = p3 + 10;
	cout << "p4.m_A==" << p4.m_A << endl;
	cout << "p4.m_B==" << p4.m_B << endl;
	//运算符重载也可以发生函数重载
	return 0;
}

在这里插入图片描述
注意:
1、内置的运算符无法重载
2、不要滥用

左移运算符重载

作用:可以输出自定义数据类型

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

class Person
{
	friend ostream& operator<<(ostream &cout, Person& p);

public:
	Person(int a, int b)
	{
		m_A = a;
		m_B = b;
	}

private:

	//利用成员函数重载 左移运算符 p.operator<<(cout) 简化版本p<<cout
	//不会利用成员函数重载<<运算符,因为无法实现cout在左侧
	//void operator<<( cout )
	//{

	//}
	int m_A;
	int m_B;
};

//只能利用全局函数重载左移运算符
ostream& operator<<(ostream &cout, Person& p)//本质 operator<<(cout,p)简化cout<<p
{
	cout << "m_A=" << p.m_A << " m_B=" << p.m_B;
	return cout;
}

void test01()
{
	Person p(10,10);
	cout << p <<endl;
}

int main()
{
	test01();
	return 0;
}

在这里插入图片描述
对于这段代码中,为什么重载函数返回ostream& 之后,cout << p 后面就可以加<<endl;
是因为cout << p之后返回的就是一个cout的引用。虽然不能滥用重载,但是为了验证cout的可行性,甚至可以将代码写成如下:

#include<iostream>
using namespace std;

ostream& operator<<(ostream &out, ostream &cout2)
{
	out << "秀儿";
	return out;
}

int main()
{
	cout << cout << endl;
	return 0;
}

输出:在这里插入图片描述
原本cout<<cout<<endl;肯定是会报错的,但是我们通过重载函数让cout<<cout能够输出一个字符串,并返回一个cout引用。意味着cout<<cout之后依然能够继续接endl或者是其他的类型数据。个人猜想cout函数应该本来就能够接受各种有官方定义数据类型并返回一个cout。

总结:重载左移运算符配合友元可以实现输出自定义数据类型

递增运算符重载

作用:通过重载递增运算符,实现自己的整型数据

#include<iostream>
using namespace std;

class MyInteger
{
	friend ostream& operator<<(ostream& cout, MyInteger myint);
public:
	MyInteger()
	{
		m_Num = 0;
	}

	//重载前置++运算符
	MyInteger& operator++()
	{
		m_Num++;
		return *this;
	}

	//重载后置++运算符
	//int代表占位参数,可以用于区分前置和后置递增
	MyInteger operator++(int)
	{
		//先返回结果
		MyInteger temp = *this;
		//后递增
		m_Num++;
		//最后将记录结果做返回
		return temp;
	}

private:
	int m_Num;
};

//重载<<运算符
ostream& operator<<(ostream& cout, MyInteger myint)
{
	cout << myint.m_Num;
	return cout;
}

void test01()
{
	MyInteger myint;
	cout << ++myint << endl;
}

void test02()
{
	MyInteger myint;
	cout << myint++ << endl;
	cout << myint << endl;
}

int main()
{
	//test01();
	test02();
	return 0;
}

问:operator++()为什么不带int就可以将++写在前面作为前置,而写成operator++(int)却能将++写在后面作为后缀?
答:
在C++中,前缀形式和后缀形式的++运算符是通过运算符重载来实现的,它们使用不同的函数签名来区分。下面我会解释为什么不同的函数签名能够达到这个效果。

  1. 前缀形式的++运算符重载函数签名为MyInteger& operator++()

    • 返回类型是一个引用(MyInteger&),表示该运算符重载函数直接在原对象上进行自增操作,并返回增加后的对象的引用。
    • 函数的形参列表为空,因为前缀形式不需要接收额外的参数。
  2. 后缀形式的++运算符重载函数签名为MyInteger operator++(int)

    • 返回类型是一个新的MyInteger对象(非引用),表示该运算符重载函数在原对象的副本上进行自增操作,并返回增加之前的副本对象。
    • 函数的形参列表中包含一个额外的 int 参数(此参数没有实际用途),用于区分前缀和后缀形式的运算符重载函数。

通过在函数签名中加入int参数(可能是任何类型的参数),可以实现与前缀形式的运算符进行区分,以便编译器能够正确选择调用哪个重载函数。

值得注意的是,后缀形式中的int参数是一个惯例,并没有实际作用,因为C++规定后缀形式的重载运算符必须具有该参数。这是为了能够和前缀形式的重载运算符区分开来,从而实现一致性和灵活性。

所以,operator++()operator++(int)是两个不同的函数,它们根据函数签名的不同来区分前缀和后缀形式的++运算符重载。这样,你就可以根据需要在变量前面或后面使用++运算符。

问:什么是重载运算符?
答:重载运算符是C++语言的一个重要特性,它允许程序员为自定义类型定义操作符的行为。通过重载运算符,你可以以自定义的方式对对象进行运算,使其适应你的特定需求。以下是一些常用的重载运算符及其相应的函数签名:

  1. 算术运算符:

    • 加法运算符:+
      ReturnType operator+(const ClassName& obj) const;
    • 减法运算符:-
      ReturnType operator-(const ClassName& obj) const;
    • 乘法运算符:*
      ReturnType operator*(const ClassName& obj) const;
    • 除法运算符:/
      ReturnType operator/(const ClassName& obj) const;
    • 取模运算符:%
      ReturnType operator%(const ClassName& obj) const;
  2. 比较运算符:

    • 等于运算符:==
      bool operator==(const ClassName& obj) const;
    • 不等于运算符:!=
      bool operator!=(const ClassName& obj) const;
    • 大于运算符:>
      bool operator>(const ClassName& obj) const;
    • 小于运算符:<
      bool operator<(const ClassName& obj) const;
    • 大于等于运算符:>=
      bool operator>=(const ClassName& obj) const;
    • 小于等于运算符:<=
      bool operator<=(const ClassName& obj) const;
  3. 赋值运算符:

    • 简单赋值运算符:=
      ReturnType& operator=(const ClassName& obj);
  4. 递增递减运算符:

    • 前置递增运算符:++
      ReturnType& operator++();
    • 后置递增运算符:++(额外的int参数用于区分前置和后置形式)
      ReturnType operator++(int);
    • 前置递减运算符:--
      ReturnType& operator--();
    • 后置递减运算符:--(额外的int参数用于区分前置和后置形式)
      ReturnType operator--(int);
  5. 索引访问运算符:

    • 下标访问运算符:[]
      ReturnType operator[](int index) const;
  6. 函数调用运算符:

    • 函数调用运算符:()
      ReturnType operator()(Args... args);
  7. 其他运算符:

    • 成员访问运算符:->
      ReturnType operator->();
    • 类型转换运算符:
      operator Type();

这只是一些常见的重载运算符示例,你可以根据自己的需要对其他运算符进行重载。重载运算符的语法和具体实现方式需要遵循一定的规则,确保符合预期的行为,并避免出现二义性或违反常规的语义。

赋值运算符重载

C++编译器至少给一个类添加4个函数
1、默认构造函数(无参,函数体为空)
2、默认析构函数(无参,函数体为空)
3、默认拷贝函数,对属性进行值拷贝
4、赋值运算符operator=,对属性进行值拷贝
如果类中有属性指向堆区,做赋值操作时也会出现深浅拷贝问题

#include<iostream>
using namespace std;

class Person
{

public:
	Person(int age)
	{
		m_Age = new int(age);
	}

	~Person()
	{
		if (m_Age != NULL)
		{
			delete m_Age;
			m_Age = NULL;
		}
	}

	//重载 赋值运算符
	Person& operator=(Person& p)
	{
		cout << "执行了重载赋值运算"  << endl;
		//编译器是提供的浅拷贝
		//m_Age=p.m_Age

		//应该先判断是否有属性在堆区,如果有先释放干净,然后再深拷贝
		if (m_Age != NULL)
		{
			if (m_Age == p.m_Age)
			{
				cout << "=两边是同一个对象" << endl;
				return *this;
			}
			else
			{
				cout << "delete了m_Age" << endl;
				delete m_Age;
				m_Age = NULL;
			}
		}
		//深拷贝
		m_Age = new int(*p.m_Age);
		return *this;
	}

	Person(const Person &p)
	{
		cout << "Person拷贝构造函数调用" << endl;
		//m_Age=p.m_Age;编译器默认实现就是这行代码
		m_Age = new int(*p.m_Age);
	}

	int* m_Age;
};

void test01()
{
	Person p1(18);
	Person p2(20);
	//Person p3 = Person(p2);//第一种方法
	//Person p3 = p2;//第二种方法
	Person p3(p2);//第三种方法
	Person p4(30);
	cout << "马上执行p2=p1" << endl;
	p2 = p1;
	cout << "马上执行p4=p3" << endl;
	p4 = p3;
	cout << "p1的年龄为:" << *p1.m_Age << endl;
	cout << "p2的年龄为:" << *p2.m_Age << endl;
	cout << "p3的年龄为:" << *p3.m_Age << endl;
	cout << "p4的年龄为:" << *p4.m_Age << endl;
	p4 = p3 = p2 = p1;
	cout << "p1的年龄为:" << *p1.m_Age << endl;
	cout << "p2的年龄为:" << *p2.m_Age << endl;
	cout << "p3的年龄为:" << *p3.m_Age << endl;
	cout << "p4的年龄为:" << *p4.m_Age << endl;
	p3 = p3 = p3 = p3 = p2 = p3 = p3;
	cout << "p3的年龄为:" << *p4.m_Age << endl;
}

int main()
{
	test01();
	return 0;
}

在这里插入图片描述

针对之前学习的内容,自行进行了探索,探索代码以及输出如下:

#include<iostream>
using namespace std;
#define CPRINT(X) cout<<#X<<" value is:"<<X<<endl

class Mydiv
{
	friend ostream& operator<<(ostream& out, Mydiv& mydiv);
public:
	Mydiv();
	Mydiv(int num);
	Mydiv(const Mydiv& mydiv);
	~Mydiv();
	Mydiv& operator=(Mydiv& mydiv);
	Mydiv& operator++();
	Mydiv operator++(int);
	Mydiv& operator--();
	Mydiv operator--(int);

	Mydiv test02(Mydiv mydiv);
private:
	int *myinter;
};

Mydiv::Mydiv()
{
	cout << "build a NULL myinter" << endl;
	myinter = NULL;
}

Mydiv::Mydiv(int num)
{
	cout << "new Mydiv" << endl;
	myinter = new int(num);
}

Mydiv::Mydiv(const Mydiv& mydiv)
{
	if (mydiv.myinter == NULL)
	{
		cout << "copy NULL Mydiv" << endl;
		myinter = NULL;
	}
	else
	{
		cout << "copy Mydiv" << endl;
		myinter = new int(*mydiv.myinter);
	}
}

Mydiv::~Mydiv()
{
	cout << "delete Mydiv" << endl;
	if (myinter != NULL)
	{
		delete myinter;
		myinter = NULL;
	}
}

Mydiv& Mydiv::operator=(Mydiv& mydiv)
{
	if (myinter != NULL)
	{
		if (myinter == mydiv.myinter)
		{
			cout << "mydiv is equal" << endl;
			return *this;
		}
		else
		{
			cout << "rebuiding mydiv" << endl;
			delete myinter;
			myinter = NULL;
		}
		if (mydiv.myinter != NULL)
		{
			myinter = new int(*mydiv.myinter);
		}
	}
	else
	{
		if (mydiv.myinter==NULL)
		{
			cout << "mydiv is equal and NULL" << endl;
			return *this;
		}
		else
		{
			myinter = new int(*mydiv.myinter);
		}
	}
	return *this;
}

Mydiv& Mydiv::operator++()
{
	if (myinter != NULL)
	{
		(*myinter)++;
	}
	else
	{
		cout << "++ NULL fail!" << endl;
	}
	return *this;
}

Mydiv Mydiv::operator++(int)
{
	if (myinter != NULL)
	{
		Mydiv tmp(*this);
		(*myinter)++;
		return tmp;
	}
	else
	{
		cout << "NULL ++ fail!" << endl;
		return *this;
	}
}

Mydiv& Mydiv::operator--()
{
	if (myinter != NULL)
	{
		(*myinter)--;
	}
	else
	{
		cout << "NULL ++ fail!" << endl;
	}
	return *this;
}

Mydiv Mydiv::operator--(int)
{
	if (myinter != NULL)
	{
		Mydiv tmp(*this);
		(*myinter)--;
		return tmp;
	}
	else
	{
		cout << "NULL ++ fail!" << endl;
		return *this;
	}
}

Mydiv Mydiv::test02(Mydiv mydiv)
{
	cout << 3 << endl;
	return mydiv;
}

ostream& operator<<(ostream& out, Mydiv& mydiv)
{
	if (mydiv.myinter == NULL)
	{
		out << "NULL";
		return out;
	}
	out << *mydiv.myinter;
	return out;
}

void test01()
{
	Mydiv p1;//构造p1但因为没传参,对象中指针没有new,为NULL
	CPRINT(p1);
	Mydiv p2(p1);//拷贝p1到一个新的对象p2,但p1中指针为NULL,因此p2中指针的值也为NULL
	CPRINT(p1);
	CPRINT(p2);
	Mydiv p3(666);//构造p3并传值666,对象中指针new了一块区域用来存放
	CPRINT(p3);
	p1 = p3 = p2 = p2;//从右到左分别将p2赋值给p2,p3,p1,最终对象中指针全指向了NULL
	CPRINT(p1);
	CPRINT(p2);
	CPRINT(p3);
	Mydiv p4(666);//构造p4并传值666,对象中指针new了一块区域用来存放
	p1 = p2 = p4;//从右到左分别将p4赋值给p2,p1,通过深拷贝的方式将666赋值给p1,p2
	CPRINT(p1);
	CPRINT(p2);
	CPRINT(p4);
	Mydiv p5(p1);//将p1的值666拷贝给新构造的p5
	CPRINT(p5);
	CPRINT(++p5);
	CPRINT(++p3);
	CPRINT(++(++p4));
	CPRINT(--(--(--p1)));
	CPRINT(p3++);
	CPRINT(p2++);
	CPRINT(p2);
}

Mydiv test03(Mydiv pp)
{
	return pp;
}

int main()
{
	test01();
	cout << 1 << endl;//从这里到cout << 4 << endl;发现在调用a.test02时拷贝和析构被调用了两次
	Mydiv a(666);
	cout << 2 << endl;
	cout << &a << endl;
	cout << &(a.test02(a)) << endl;
	cout << 4 << endl;
	Mydiv cc(666);
	Mydiv* pp1 = &cc;
	Mydiv* pp2 = &(test03(cc));
	cout << pp1 << endl;
	cout << *pp1 << endl;
	cout << pp2 << endl;
	cout << *pp2 << endl;//*pp2的值为NULL证明了test03返回的对象在该语句执行完成后自动析构了
	return 0;
}

在这里插入图片描述

关系运算符重载

作用:重载关系运算符,可以让两个自定义类型对象进行对比操作

#include<iostream>
using namespace std;

//重载关系运算符

class Person
{
public:
	Person(string name, int age)
	{
		m_Name = name;
		m_Age = age;
	}

	//重载==号


	bool operator==(Person& p)
	{
		if (this->m_Name == p.m_Name&&this->m_Age == p.m_Age)
		{
			return true;
		}
		return false;
	}

	bool operator!=(Person& p)
	{
		if (this->m_Name == p.m_Name&&this->m_Age == p.m_Age)
		{
			return false;
		}
		return true;
	}

	string m_Name;
	int m_Age;
};

void test01()
{
	Person p1("Tom", 18);
	Person p2("Tom", 18);
	if (p1 == p2)
	{
		cout << "p1和p2是相等的!" << endl;
	}
	else
	{
		cout << "p1和p2是不相等的!" << endl;
	}

	if (p1 != p2)
	{
		cout << "p1和p2是不相等的!" << endl;
	}
	else
	{
		cout << "p1和p2是相等的!" << endl;
	}
}

int main()
{
	test01();
	return 0;
}

函数调用运算符重载

1、函数调用运算符()也可以重载
2、由于重载后使用的方式非常像函数的调用,因此称为仿函数
3、仿函数没有固定的写法,非常灵活

#include<iostream>
using namespace std;
#include <string>

//函数调用运算符重载

class MyPrint
{
public:
	//重载函数调用运算符
	void operator()(string test)
	{
		cout << test << endl;
	}
};

void MyPrint02(string test)
{
	cout << test << endl;
}

void test01()
{
	MyPrint myPrint;
	myPrint("hello world");//仿函数
	MyPrint02("hello world");
}

class Myadd
{
public:
	int operator()(int num1, int num2)
	{
		return num1 + num2;
	}
};

void test02()
{
	Myadd myadd;
	int ret=myadd(100, 100);
	cout << "ret = " << ret << endl;

	//匿名函数对象
	cout << Myadd()(100, 100) << endl;
}

int main()
{
	test01();
	test02();
	return 0;
}

在这里插入图片描述

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

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

相关文章

vue 使用百度地图记录

参考文档 https://lbsyun.baidu.com/index.php?titlejspopular3.0/guide/infowindow https://lbsyun.baidu.com/cms/jsapi/reference/jsapi_reference_3_0.html#a0b0 1.百度地图标注点点击出现infoWindow信息窗口添加点击事件 var opts {width: 200, // 信息窗口宽度height:…

【TS】学习笔记

1、所有的JavaScript代码都是有效的Typescript代码&#xff0c;用TypeScript编译器编译TypeScript里的Javascript代码&#xff0c;编译后的结果与原始的Javascript代码一模一样&#xff0c;即文件扩展名从.js改为.ts&#xff0c;不会造成任何负面的影响 2、JavaScript代码迁移…

idea将代码片段提取成一个方法快捷方式

CtrlAltM 今天写代码发现有的方法太长了&#xff0c;为了使我们的代码更加简洁&#xff0c;就可以使用idea的这个功能 效果如图 改造前&#xff1a; 提取出两个方法 如何使用

Bootloader Design of PIC18 series MCU - 进阶篇

1.遭遇到问题 在&#xff1a;PIC18 Bootloader 设计基础 一文中&#xff0c;我们讨论了Bootloader与上层应用APP各自编译的方法。在ROM上的空间分配、以及跳转、中断的处理等内容。那篇文章包含了所有与PIC单片机Bootloader设计相关的技术问题。但是距离一个真正可用的Bootloa…

python接口自动化(二十一)--unittest简介(详解)

简介 前边的随笔主要介绍的requests模块的有关知识个内容&#xff0c;接下来看一下python的单元测试框架unittest。熟悉 或者了解java 的小伙伴应该都清楚常见的单元测试框架 Junit 和 TestNG&#xff0c;这个招聘的需求上也是经常见到的。python 里面也有单元 测试框架-unitt…

element table列表根据数据设置背景色

效果 页面代码 通过:cell-class-name动态绑定类名 <el-table :data"tableData" style"width: 100%" :cell-class-name"myclass"><el-table-column prop"date" label"日期" width"180"> </el-ta…

pytest测试框架的基本使用与介绍

pytest介绍 pytest是一个非常成熟的全功能的Python测试框架&#xff0c;主要特点有以下几点&#xff1a; 1、简单灵活&#xff0c;容易上手&#xff0c;文档丰富&#xff1b; 2、支持参数化&#xff0c;可以细粒度地控制要测试的测试用例&#xff1b; 3、能够支持简单的单元测…

Jenkins---jenkins生成Allure报告

目录 前言 Allure插件安装 生成Allure报告 遇到的问题 总结&#xff1a; 前言 前几天介绍了如何生成html报告&#xff0c;目前绝大部分公司都是用的allure报告&#xff0c;那么今天也介绍下如何通过jenkins生成allure报告。 Allure插件安装 jenkins中存在支持allure报告…

Pytorch从入门到精通:一、准备工作与查询函数

之前虽然做了不少计算机视觉的项目&#xff0c;但是如果让我从0还是用Pytorch开始写的话还是有一点难度。原因就在于没有系统的学习Pytorch&#xff0c;对于里面的不少模块都只知道使用&#xff0c;不知道原理&#xff0c;知道它能工作&#xff0c;但是不知道怎么样工作的。所以…

QT - 20230707

登录界面练习 #include "loginwindow.h"QIcon fetchIconWithName(QString name) {QString res "../login/images/" name;return QIcon(res); }LoginWindow::LoginWindow(QWidget *parent): QMainWindow(parent) {this->resize(600, 800);this->se…

小红书私信软件:把微信二维码联系方式隐藏在图片中推广引流找客源

小红书私信软件&#xff1a;把微信二维码联系方式隐藏在图片中推广引流找客源,小红书还能这么玩&#xff1f;小红书暑期聊天功能上新了&#xff0c;共享收藏夹、斗图神器&#xff0c;暑期表情&#xff0c;笔记表态....快去和好友一起解锁新功能吧&#xff01; #小红书 最近发现…

YOLOv5-第Y1周:调用官方权重进行检测

YOLOv5-第Y1周&#xff1a;调用官方权重进行检测 YOLOv5-第Y1周&#xff1a;调用官方权重进行检测一、前言二、我的环境三、下载源码四、运行代码五、视频检测八、总结 YOLOv5-第Y1周&#xff1a;调用官方权重进行检测 一、前言 &#x1f368; 本文为&#x1f517;365天深度学…

【Redis-工具类】自定义Redis工具类并使用其进行简单操作

【Redis-工具类】自定义Redis工具类并使用其进行简单操作 1&#xff09;自定义 Redis 工具类2&#xff09;工具类的简单使用 1&#xff09;自定义 Redis 工具类 package gaei.cn.x5l.x5lhive2cos.utils;import gaei.cn.x5l.x5lhive2cos.CosDataBackupHistory; import gaei.cn.…

AI智能化数据分析,赋能文旅直播发展新赛道

一、文旅直播发展背景 近期&#xff0c;旅游业市场呈现火热态势。暑期旅游市场预计迎来新一轮旅游小高峰&#xff0c;旅游业进入结构性复苏新阶段。而随着社交媒介的普及与旅游直播的兴起&#xff0c;全国多地文旅“出圈”形成热议。 对于文旅产业发展来说&#xff0c;高品质…

【如何在工作中保持稳定的情绪 --- 保持稳定情绪的7个工作技巧】

导语&#xff1a; 在现代工作环境中&#xff0c;保持稳定的情绪是一项至关重要的技能。当我们遇到挑战、压力和严峻的工作条件时&#xff0c;情绪的稳定性对于我们的工作效率和心理健康至关重要。本文将分享七个实用的工作技巧&#xff0c;帮助你保持稳定的情绪并提升工作质量…

面对chatGPT,冷静比鸡血更重要!

这段时间 chatGPT 也算是疯狂的吸引眼球了。 看起来广告费没白花&#xff0c;不管说的对不对&#xff0c;反正说它一定要用**“颠覆”“天花板”“惊艳”“抢大多数人的饭碗”**之类的词。 再大一点的描述就是&#xff1a;留给人类的时间不多了。扼腕叹息、杞人类生存空间而忧…

springboot项目开启https协议

1、在windows以管理员身份运行cmd,输入如下命令生成证书 keytool -genkey -alias myhttps -keyalg RSA -keysize 2048 -validity 36500 -keystore "D:/tmp/ssl/myhttps.keystore"注释 命令&#xff1a;keytool -genkey -alias testhttps -keyalg RSA -keysize 204…

蓝牙资讯|苹果Beats Studio Pro耳机曝光,支持苹果和谷歌的查找功能

国外科技媒体9to5Mac曝光苹果Beats Studio Pro耳机&#xff0c;这款耳机配备了 2 个定制的 40 毫米驱动单元&#xff0c;即便是在最高音量下&#xff0c;也能确保不会失真。Beats Studio Pro 还将配备集成的数字处理器&#xff0c;该处理器“优化最终频率响应&#xff0c;以获得…

Jetpack 架构组件你了解多少?

本文是我在学习Jetpack的过程中做的一些记录&#xff0c;如有错误&#xff0c;欢迎指正 本文包含了 ViewModel、Lifecycles、LiveData、Room、WorkManager 的相关用法&#xff0c;你可以通过目录直接跳转到你想了解的地方 ViewModel 简单介绍下 ViewModel&#xff1a;ViewMode…

DataWhale: LLM+KG

https://mp.weixin.qq.com/s/MIi1WrAwfmqnXGlkQq8DqQ