33 类与对象 · 下

目录

一、构造函数的深入

(一)构造函数的其他特点

(二)使用例

1、Date类与Time类显示写

2、Date类与Time类写一部分

(三)总结

(四)初始化顺序小题目

二、类型转化

(一)内置类型转化到自定义类型

(二)自定义类型转自定义类型

(三)实现例

(四)总结

三、静态成员

(一)静态成员的特点

(二)使用例

(三)练习题目

1、题目一

2、题目二

四、友元

(一)友元的特点

(二)使用例

        1、友元函数

        2、友元类

五、内部类

(一)内部类特点

(二)代码实现

六、匿名对象

(一)匿名对象特点

(二)使用例

(三)总结

七、编译器优化


一、构造函数的深入

(一)构造函数的其他特点

        • 之前我们实现构造函数时,初始化成员变量主要使用函数体内赋值,构造函数初始化还有一种方式,就是初始化列表,初始化列表的使用方式是以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个【放在括号中的】初始值或表达式。简单来说,就是:跟在参数成员列表后面,冒号开始,逗号分隔,没有结束符号(每个成员变量只能初始化一次)

        • 每个成员变量在初始化列表中只能出现一次,在语法理解上可以认为初始化列表是每个成员变量定义初始化的地方

        • 引用成员变量const成员变量没有默认构造的类类型变量(三种构造函数都没有),必须放在初始化列表位置进行初始化,否则会编译报错。【为什么是这三类:①引用成员变量只能在在定义时初始化,不存在空引用。②const修饰成员变量只能在定义时进行初始化,因为定义时初始化时唯一一次能改变变量的机会。③类类型的成员变量没有默认构造函数的话就会报错。

        • C++11支持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显示在初始化列表初始化的成员使用的。

        • 尽量使用初始化列表初始化,因为那些你不在初始化列表进行初始化的成员也会过一次初始化列表,如果这个成员在声明位置给了缺省值,初始化列表会用这个缺省值初始化。如果你没有给缺省值,对于没有显示在初始化列表进行初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。对于没有显示在初始化列表初始化的自定义类型成员会调用这个成员类型的默认构造函数,如果没有默认构造会编译错误。

        • 初始化列表中按照成员变量在类中声明顺序进行初始化,跟成员在初始化列表出现的的先后顺序无关。建议声明顺序和初始化列表顺序保持一致。

(二)使用例

1、Date类与Time类显示写

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

class Time
{
public:
	Time(int hour)//无默认构造(三种)
		:_hour(hour)
	{
		cout << "Time()" << endl;
	}
private:
	int _hour;
};

class Date
{
public:
	Date(int& x, int year = 1, int month = 1, int day = 1)
		:_year(year)//初始化列表
		, _month(month)
		, _day(day)
		, _t(12)
		, _ref(x)
		, _n(1)
	{
		// error C2512: “Time”: 没有合适的默认构造函数可用,必须在初始化列表进行初始化
		// error C2530 : “Date::_ref” : 必须初始化引用(&)
		// error C2789 : “Date::_n” : 必须初始化常量限定(const)类型的对象
	}
	void Print() const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
	Time _t; // 没有默认构造
	int& _ref; // 引用
	const int _n; // const
};
int main()
{
	int i = 0;
	Date d1(i);
	d1.Print();
	return 0;
}

2、Date类与Time类写一部分

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

class Time
{
public:
	Time(int hour)
		:_hour(hour)
	{
		cout << "Time()" << endl;
	}
private:
	int _hour;
};

class Date
{
public:
	Date()
		:_month(2)
	{
		cout << "Date()" << endl;
	}
	void Print() const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	// 注意这里不是初始化,这里给的是缺省值,这个缺省值是给初始化列表的
	// 如果初始化列表没有显示初始化,默认就会用这个缺省值初始化
	int _year = 1;
	int _month = 1;
	int _day;
	Time _t = 1;
	const int _n = 1;
	int* _ptr = (int*)malloc(12);
};

int main()
{
	Date d1;
	d1.Print();
	return 0;
}

(三)总结

        无论是否显示写初始化列表,每个构造函数都有初始化列表。

         无论是否在初始化列表显示写初始化,每个成员变量都要走一次初始化列表进行初始化,所以构造函数初始化成员,尽量使用初始化列表

        ③ 在main函数进行的是整体对象的初始化,在初始化列表中是对每个成员变量的初始化。

        ④ 可以使用初始化列表进行初始化,也可以使用函数体中的构造函数进行初始化;可以两者取其一,也可以一起都用。

        ⑤ 可以在成员变量声明的时候给缺省值,若在初始化列表中对成员变量进行了初始化,那么缺省值就会被忽视,反之就会使用缺省值。

        ⑥ 初始化优先级:初始化列表 > 缺省值 > 默认构造函数(无默认构造就报错)。

(四)初始化顺序小题目

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

class A
{
public:
	A(int a)
		:_a1(a)
		, _a2(_a1)
	{}
	void Print() {
		cout << _a1 << " " << _a2 << endl;
	}
private:
	int _a2 = 2;
	int _a1 = 2;
};

int main()
{
	A aa(1);
	aa.Print();
}

        结果为:1和随机值。

        解析:初始化顺序要看成员变量声明的顺序,不看初始化列表的顺序;所以先初始化_a2,但_a1还没进行初始化且是内置类型,此时_a1的值为随机值,所以_a2为随机值,初始玩_a2后再把传过去的1初始化_a1,此时_a1就是1。

二、类型转化

(一)内置类型转化到自定义类型

        • C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数

        •  构造函数前面加 explicit 就不再支持隐式类型转换。

          内置类型转化到自定义类型作用:简化写法。

(二)自定义类型转自定义类型

        • 类类型的对象之间也可以隐式转换,需要相应的构造函数支持。

(三)实现例

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;

class A
{
public:
	// 使用构造函数explicit就不再支持隐式类型转换
	// explicit A(int a1)
	A(int a1)//普通构造
		:_a1(a1)
	{}
	//explicit A(int a1, int a2)
	A(int a1, int a2)//普通构造
		:_a1(a1)
		, _a2(a2)
	{}
	void Print()
	{
		cout << _a1 << " " << _a2 << endl;
	}
	int Get() const
	{
		return _a1 + _a2;
	}
private:
	int _a1 = 1;
	int _a2 = 2;
};

class B
{
public:
	B(const A& a)
		:_b(a.Get())
	{}
private:
	int _b = 0;
};

int main()
{
	
	A aa1 = 1;
	aa1.Print();
	// 使用1构造一个A的临时对象,再用这个临时对象拷贝构造aa1
	// 编译器遇到连续的【构造+拷贝构造】->优化为直接构造

	const A& aa2 = 1;
	//使用const检测是否是先使用1构造一个临时对象,因为临时对象具有常性

	A aa3 = { 2,2 };
	// C++11之后才支持多参数转化(使用大括号)
	// aa3隐式类型转换为b对象
	// 原理跟上面类似(传两个参数进行构造创建临时对象,再把临时对象拷贝构造给aa3)

	B b = aa3;
	// 类类型之间的转化过程也和上面的类似
	// 使用aa3构造一个B的临时对象,再用这个临时对象拷贝构造b
	const B& rb = aa3;
	//使用const检测是否是先使用aa3构造一个临时对象,因为临时对象具有常性

	return 0;
}

(四)总结

        ① 内置类型到自定义类型的转化过程:先构造成临时对象,再拷贝构造,被优化为直接进行构造。

        ② 自定义类型到自定义类型的转化过程:先构造成临时对象,再拷贝构造,被优化为直接进行构造。

        ③ 多参数转化需要加大括号 { }

        ④ 可以使用const 引用进行检测。(因为类型转化后是临时变量,有常性)

       

三、静态成员

(一)静态成员的特点

        • static修饰的成员变量,称之为静态成员变量,静态成员变量一定要在类里面进行声明,在类外进行初始化(原因如下点所示)。

        • 静态成员变量为所有类对象所共享,不属于某个具体的对象,不存在对象中,存放在静态区。(可以理解为把全局的静态变量放在类中,变成类的专属且受类域的限制

        • static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针

        • 静态成员函数中可以访问其他的静态成员,但是不能访问非静态的成员变量,因为没有this指针。

        • 非静态的成员函数,可以访问任意的静态成员变量和静态成员函数

        • 突破类域就可以访问静态成员,可以通过【类名::静态成员 】或者【对象.静态成员】来访问静态成员变量和静态成员函数。

        • 静态成员也是类的成员,受public、protected、private 访问限定符的限制。

        • 静态成员变量不能在声明位置给缺省值初始化,因为缺省值是个构造函数初始化列表的,静态成员变量不属于某个对象,不走构造函数初始化列表。

(二)使用例

#define _CRT_SECURE_NO_WARNINGS 1

// 实现⼀个类,计算程序中创建出了多少个类对象?
#include<iostream>
using namespace std;
class A
{
public:
	A()//默认构造
	{
		++_scount;
	}
	A(const A& t)//拷贝构造
	{
		++_scount;
	}
	~A()//析构
	{
		--_scount;
	}
	static int GetACount()
	{
		return _scount;
	}
private:
	// 类里面声明
	static int _scount;
};
// 类外面初始化
int A::_scount = 0;

int main()
{
	cout << A::GetACount() << endl;//0
	A a1, a2;
	A a3(a1);
	cout << A::GetACount() << endl;//3
	cout << a1.GetACount() << endl;//3

	// 编译报错:error C2248: “A::_scount”: 无法访问 private 成员(在“A”类中声明,受A类的影响)
	//cout << A::_scount << endl;
	return 0;
}

        scount是全局的静态变量,每次构造或拷贝构造都让scount++,所以打印出来的结果是0,3,3。

(三)练习题目

1、题目一

题目答案代码:

class Sum
{
public:
    Sum()
    {
        _rel += _num;
        _num++;
    }

    static int get_rel()
    {
        return _rel;
    }

private:
    static int _rel;
    static int _num;
};

int Sum::_rel = 0;
int Sum::_num = 1;

class Solution {
public:
    int Sum_Solution(int n) {
        Sum arr[n];
        return Sum::get_rel();
    }
};

        题目思路:

        因为限制条件的原因,剩下连续创建的方法就是数组,而类类型在定义时会自动调用构造函数,那么在构造函数中完成加法;此时需要数据连续的储存,就使用静态变量来声明与初始化,又因为静态变量受到类的限制,需要提供一个可以获得其值的函数,该函数可以使用静态函数来写,这样可以随时调用,而不需要具体的某个对象。

2、题目二

        设已经有A,B,C,D 4个类的定义:

        程序中A,B,C,D构造函数调用顺序为?

        析构函数调用顺序为?

C c;
int main()
{
	A a;
	B b;
	static D d;
	return 0;
}

        答:

                构造顺序:c a b d,顺序调用

                析构顺序:b a d c,先调用的后析构,先局部后静态再到全局。

四、友元

(一)友元的特点

        • 友元提供了一种突破类访问限定符封装的方式,友元分为:友元函数和友元类在函数声明或者类声明的前面加friend,并且把友元声明放到一个类的里面。

        • 外部友元函数可访问类的私有和保护成员,友元函数仅仅是一种声明,他不是类的成员函数。

        • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。

        • 一个函数可以是多个类的友元函数。

        • 友元类中的成员函数都可以是另⼀个类的友元函数,都可以访问另一个类中的私有和保护成员。

        • 友元类的关系是单向的,不具有交换性,比如A类是B类的友元,但是B类不是A类的友元。

        • 友元类关系不能传递,如果A是B的友元, B是C的友元,但是A不是C的友元。

        • 有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用

(二)使用例

1、友元函数

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;
// 前置声明,都则A的友元函数声明编译器不认识B
class B;
class A
{
	// 友元声明
	friend void func(const A& aa, const B& bb);
private:
	int _a1 = 1;
	int _a2 = 2;
};
class B
{
	// 友元声明
	friend void func(const A& aa, const B& bb);
private:
	int _b1 = 3;
	int _b2 = 4;
};
void func(const A& aa, const B& bb)
{
	cout << aa._a1 << endl;
	cout << bb._b1 << endl;
}
int main()
{
	A aa;
	B bb;
	func(aa, bb);
	return 0;
}

        注意:一个函数可以是多个类的友元函数,不过要让后面的类在前一个类中作友元声明,这样编译器才认识友元函数中的多个类的成员变量。

2、友元类

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class A
{
	// 友元声明
	friend class B;
private:
	int _a1 = 1;
	int _a2 = 2;
};
class B
{
public:
	void func1(const A& aa)
	{
		cout << aa._a1 << endl;
		cout << _b1 << endl;
	}
	void func2(const A& aa)
	{
		cout << aa._a2 << endl;
		cout << _b2 << endl;
	}
private:
	int _b1 = 3;
	int _b2 = 4;
};
int main()
{
	A aa;
	B bb;
	bb.func1(aa);
	bb.func1(aa);
	return 0;
}

五、内部类

(一)内部类特点

        • 如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制(与静态成员类似),所以外部类定义的对象中不包含内部类(并不是外部类的成员)。

        • 内部类默认是外部类的友元类。

        • 内部类本质也是一种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使用,那么可以考虑把A类设计为B的内部类,如果放到 private / protected 位置,那么A类就是B类的专属内部类,其他地方都用不了。

(二)代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class A
{
private:
	static int _k;
	int _h = 1;
public:
	class B // B默认就是A的友元
	{
	public:
		void foo(const A& a)
		{
			cout << _k << endl; //OK
			cout << a._h << endl; //OK
		}
	};
};
int A::_k = 1;
int main()
{
	cout << sizeof(A) << endl;
	A::B b;
	A aa;
	b.foo(aa);
	return 0;
}

        注意:这种用法用的比较少。

六、匿名对象

(一)匿名对象特点

        • 用【类型(实参) 定义出来的对象叫做匿名对象,相比之前我们定义的 【类型 对象名(实参) 】定义出来的叫有名对象。

        • 匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下即可,就可以定义匿名对象。

(二)使用例

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class A
{
public:
	A(int a = 0)
		:_a(a)
	{
		cout << "A(int a)" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a;
};
class Solution {
public:
	int Sum_Solution(int n) {
		//...
		return n;
	}
};
int main()
{
	A aa1;
	// 不能这么定义对象,因为编译器无法识别下面是一个函数声明,还是对象定义
	// A aa1();
	// 但是我们可以这么定义匿名对象,匿名对象的特点不用取名字,
	// 但是他的⽣命周期只有这一行,我们可以看到下一行他就会自动调用析构函数
	A();
	A(1);
	A aa2(2);
	// 匿名对象在这样场景下就很好用,当然还有一些其他使用场景,这个我们以后遇到了再说
	Solution().Sum_Solution(10);
	return 0;
}

(三)总结

        ① 匿名对象实例化时无参也要加括号。

        ② 类似于一次性用品。

        ③ 在函数中参数为类类型且需要给缺省值那么可以使用匿名对象。

void Fun(A aa = A(1))
{
    //业务代码
}

        ④ 引用匿名对象需要使用const,因为临时对象具有常性;被引用后会延长其生命周期,生命周期看aa对象。

const A& aa = A();

七、编译器优化

        • 现代编译器会为了尽可能提高程序的效率,在不影响正确性的情况下会尽可能减少一些传参和传返回值的过程中可以省略的拷贝。

        • 如何优化C++标准并没有严格规定,各个编译器会根据情况自行处理。当前主流的相对新一点的编译器对于连续一个表达式步骤中的连续拷贝会进行合并优化,有些更新更"激进"的编译器还会进行跨行跨表达式的合并优化。

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class A
{
public:
	A(int a = 0)
		:_a1(a)
	{
		cout << "A(int a)" << endl;
	}
	A(const A& aa)
		:_a1(aa._a1)
	{
		cout << "A(const A& aa)" << endl;
	}
	A& operator=(const A& aa)
	{
		cout << "A& operator=(const A& aa)" << endl;
		if (this != &aa)
		{
			_a1 = aa._a1;
		}
		return *this;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1 = 1;
};
void f1(A aa)
{}
A f2()
{
	A aa;
	return aa;
}
int main()
{
	// 传值传参
	A aa1;//构造
	f1(aa1);//传参需要拷贝构造
	cout << endl;
	// 隐式类型,连续构造+拷贝构造 -> 优化为直接构造

	f1(1);//1构造为临时的A对象,传参需要拷贝构造 -> 优化为直接构造
	f1(A(2));//构造一个匿名对象,传参需要拷贝构造 -> 优化为直接构造
	cout << endl;
	// 一个表达式中,连续构造+拷贝构造->优化为一个构造

	cout << "***********************************************" << endl;
	
	f2();//返回值拷贝构造给一个临时对象,临时对象再拷贝构造给接收值(vs2019)
	cout << endl;
	// 传值返回
	// 返回时一个表达式中,连续拷贝构造+拷贝构造->优化一个拷贝构造 (vs2019 debug)
	// 一些编译器会优化得更厉害,进行跨行合并优化,直接变为构造。(vs2022 debug)

	A aa2 = f2();//返回值拷贝构造给一个临时对象,临时对象再拷贝构造给接收值(vs2019)
	cout << endl;
	// 返回时一个表达式中,连续拷贝构造+拷贝构造->优化一个拷贝构造 (vs2019 debug)
	// 一些编译器会优化得更厉害,进行跨行合并优化,直接变为构造。(vs2022 debug)
	
	aa1 = f2();
	cout << endl;
	// 一个表达式中,连续拷贝构造+赋值重载->无法优化

	return 0;
	
}

        以上内容仅供分享,若有错误,请多指正。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux Redis查询key与移除日常操作

维护老项目Express node 编写的后端程序、有这么一个方法、没有设置redis过期时间&#xff08;建议设置过期时间&#xff0c;毕竟登录生产服务器并不是每个人都有权限登录的&#xff01;&#xff01;&#xff01;&#xff09;。如果变动只能通过登录生产服务器、手动修改… 于…

@Autowired和@Resource的用法与区别

前言&#xff1a; Autowired 和 Resource 来自不同的“父类”&#xff0c;其中 Autowired 是 Spring 定义的注解&#xff0c;而 Resource 是 Java 定义的注解&#xff0c;它来自于 JSR-250&#xff08;Java 250 规范提案&#xff09;。当它们的实现类只有一个时&#xff0c;那…

github pages + hugo 搭建静态博客网站

体验地址 1. 起因&#xff0c; 目的: 其实6年前&#xff0c;我就写过这个。 项目代码 博客地址 最近想改写一下。 github 推荐的主题是 Jekyll&#xff0c; 我当时用的就是这个&#xff0c;感觉很麻烦。尤其是文章命名。 新的主题 hugo 用起来还行。 2.过程: 过程记录&am…

代码随想录算法训练营第六天|454四数相加II、 383赎金信、15三数之和、18四数之和

day06 1. 454四数相加II 首先定义 一个unordered_map&#xff0c;key放a和b两数之和&#xff0c;value 放a和b两数之和出现的次数。遍历大A和大B数组&#xff0c;统计两个数组元素之和&#xff0c;和出现的次数&#xff0c;放到map中。定义int变量count&#xff0c;用来统计 …

新电脑Win11家庭中文版跳过联网激活方法(教程)

预装Win11家庭中文版的新电脑&#xff0c;如何跳过联网激活&#xff1b;由于微软限制必须要联网激活&#xff0c;需要使用已有的微软账户登入或者注册新的微软账户后才可以继续开机使用&#xff0c;Win11联网后系统会自动激活。下面介绍一下初次开机初始化电脑时如何跳过联网激…

虚拟滚动列表如何实现?

highlight: a11y-dark 虚拟滚动列表&#xff0c;虚拟滚动的关键在于只渲染当前视口内可见的数据项&#xff0c;而不是一次性渲染所有数据项。这可以显著提高性能&#xff0c;尤其是在处理大量数据时。 以下是一个完整的虚拟滚动列表的示例代码&#xff1a; <!DOCTYPE htm…

RFC2616 超文本传输协议 HTTP/1.1

一、URL-俗称“网址” HTTP 使用 URL(Uniform Resource Locator&#xff0c;统一资源定位符)来定位资源&#xff0c;它是 URI(Uniform Resource Identifier&#xff0c;统一资源标识符)的子集&#xff0c;URL 在 URI 的基础上增加了定位能力 URI 除了包含 URL&#xff0c;还包…

ADC的交流参数

ADC的交流参数是衡量其在处理交流信号时性能的关键指标。一般包括&#xff1a; 1 信噪比&#xff08;Signal-to-Noise Ratio, SNR&#xff09; 这是衡量ADC输出信号中有用信号与噪声水平的比值。信噪比越高&#xff0c;表示ADC的性能越好。 SNR (dB) MaxRMSSignal / RMSNoise…

【你也能从零基础学会网站开发】 SQL Server结构化查询语言数据操作应用--DML篇 select语句数据查询操作详解 今天干货满满!《1024特别篇》

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 select查询语句…

百度ocr服务自动实现文字识别、图片识别功能

百度ocr服务个人注册使用 介绍一个百度免费的ocr服务&#xff0c;通过调用SDK实现文字、图片识别等功能 1. 复制地址到自己的浏览器打开 https://cloud.baidu.com/doc/OCR/index.html2. 选择【登录】 3. 使用【短信登录】 4. 登录后需要选择【个人刷脸实名认证】 百度官方网…

第5.2章|25考研复试综合素质面试最常见问题50问【附上完整答案】超详细考研机械复试面试经验总结全流程 考研复试调剂问题看这一篇就够了!

接着上一章节的内容我们继续完善这50问的题目。上章节的内容参考这个文章。 第5.1章|25考研复试综合素质面试最常见问题50问【附上完整答案】超详细考研复试面试经验总结全流程 考研复试问题看这一篇就够了!考研复试调剂面试问题-CSDN博客https://blog.csdn.net/weixin_56510…

Linux基础命令(六)之 cut,sort,uniq,tr

目录 一&#xff0c;切割显示cut 参数及其作用 常见用法 二&#xff0c;排序显示sort 参数及其作用 常见用法 三&#xff0c;去重显示uniq 常见用法 四&#xff0c;替换文件中的字符显示tr 参数及其作用 常见用法 一&#xff0c;切割显示cut 用于按列提取文本内容 语…

Redis学习笔记(三)--Redis客户端

文章目录 一、命令行客户端二、图形界面客户端1、Redis Desktop Manager2、RedisPlus 三、java代码客户端 本文参考&#xff1a; Redis学习汇总&#xff08;已完结&#xff09; Redis超详细入门教程&#xff08;基础篇&#xff09; Redis视频从入门到高级&#xff0c;redis视频…

Text实现美团部分样式

Text基础 首先是Text的相关基础。 https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-basic-components-text-0000001815927600 Text是显示一段文本的组件。 可以包含Span、ImageSpan、SymbolSpan和ContainerSpan子组件。 接口 Text(content?: string | …

基于SpringBoot设计模式之结构型设计模式·桥接模式

文章目录 介绍开始架构图定义类的功能定义类的实现 测试样例 总结 介绍 将抽象部分与它的实现部分分离&#xff0c;使他们都可以独立地发生变化。 Bridge的意思是桥梁。就像在现实世界中&#xff0c;桥梁的功能是将河流的两侧连接起来一样, Bridge模式的作用也是将两样东西连接…

西南大学的计算机怎么样?

C哥专业提供——计软考研院校选择分析专业课备考指南规划 西南大学计算机学院2024届考研呈现"背道而驰"的走势&#xff0c;学硕(计算机科学与技术)分数线大幅提升23分至333分&#xff0c;而专硕(电子信息)分数线大幅下降30分至300分。学硕实际录取36人&#xff0c;复…

安装vue发生异常:npm ERR! the command again as root/Administrator.

一、异常 npm ERR! The operation was rejected by your operating system. npm ERR! Its possible that the file was already in use (by a text editor or antivirus), npm ERR! or that you lack permissions to access it. npm ERR! npm ERR! If you believe this might b…

AI创作3款软件分享,助力内容创作者高效产出优质作品

为了增加创造力和作品质量&#xff0c;许多创作者开始利用人工智能辅助工具。这些工具不仅可以帮助我们迅速生成各种类型的内容&#xff0c;例如文章、绘画、视频广告等&#xff0c;还提供语法检查和优化建议等实用功能。本文将向大家推荐三款适用于Ai先行者、Tracup、Adoe Fir…

PDF.js的使用及其跨域问题解决

目录 一、PDF.js 简介 二、使用配置和步骤 1.引入PDF.js 2.加载PDF文件 3.渲染PDF页面 三、在Vue中使用PDF.js示例 1.安装PDF.js 2.在Vue组件中使用 四、在原生js中使用PDF.js示例 1.加载PDF文件并渲染页面 五、解决跨域问题 1.服务器配置 2.使用代理服务器 下面介…

【大模型】3分钟了解提示(Prompt)工程、检索增强(RAG)和微调

我们先看下面这个图&#xff1a; 简单理解大模型是通过海量训练数据训练出来的&#xff0c;它的能力非常强&#xff0c;但是有时候会给出错误的回答。那产生错误的原因可能是什么呢&#xff1f; 1.提问错误&#xff08;提示工程&#xff09; 在我们提问的方式不对的情况下&a…