当前位置: 首页 > news >正文

C++——类和对象之运算符重载

运算符重载

本章思维导图:

在这里插入图片描述

注:本章思维导图对应的xmind文件和.png文件都已同步导入至”资源“


文章目录

  • 运算符重载
    • @[toc]
  • 1. 运算符重载的意义
  • 2. 函数的声明
    • 2.1 声明运算符重载的注意事项
  • 3. 函数的调用
  • 4. const成员函数
    • 4.1 const成员函数的声明
    • 4.2 注意点
  • 5. 两个默认成员函数
    • 5.1 赋值运算符重载
      • 5.1.1 函数的声明
      • 5.1.2 函数的定义
      • 5.1.3 赋值运算符重载和拷贝构造的区别
      • 5.1.4 默认赋值运算符重载
    • 5.2 &和const &运算符重载
  • 6. 流插入<<、流提取>>运算符重载
    • 6.1 函数的声明
  • 7. Date类的实现
    • 7.1 对于部分代码的说明

1. 运算符重载的意义

我们都知道,对于内置类型我们是可以直接用运算符直接对其进行操作的,但是对于自定义类型,这种做法是不被允许的

例如对于Date类:

Date d1;
Date d2(2023, 11, 3);d1 == d2;
//会报错:error C2676: 二进制“==”:“Date”不定义该运算符或到预定义运算符可接收的类型的转换

因此,为了解决自定义类型不能使用操作符的问题,C++就有了运算符重载

2. 函数的声明

在这里插入图片描述

一般来说,运算符重载的函数最好声明在类里面,这样就可以使用被private修饰的成员变量

声明方式:

operator 运算符 形参列表

  • 函数的返回值应该和运算符的意义相对应。例如对于比较运算符>、==就应该返回bool值,对于+、-就应该返回当前类类型
  • 函数的形参个数应该和运算符的操作数相对应

例如,我们要声明定义一个Date += 整数的函数,那我们就要重载运算符+=

//根据+=运算符的意义,其返回值应该是操作数本身,因此返回其引用
Date& operator +=(int day)
{//仅作为运算符重载如何声明定义的演示//实现细节先不做说明return *this;
}

2.1 声明运算符重载的注意事项

有小伙伴可能注意到:为什么Date& operator +=(int day)的形参只有一个day,不是说形参个数要和运算符的操作数对应吗?

我们不能忘记:在类的成员函数中,都有一个默认的形参this指针来指向当前的对象

同时还应该注意以下几点:

  • 不能通过连接其他符号来实现重载,例如operator @()是不被允许的
  • 不能修改内置类型运算符的意义
  • .* . :? sizeof ::这五个运算符是不可以重载的
  • 对于二元运算符(操作数为2的运算符),形参列表的第一个参数为左操作数,第二个参数为右操作数。因此对于声明在类里面的重载函数,this指针永远是左操作数

3. 函数的调用

在这里插入图片描述

在声明定义好运算符重载后,有两种调用方法:

第一种——像内置类型一样直接使用运算符

d1 += 10;
//调用Date& operator +=(int day)函数,在对象d1的基础上加10

第二种——像调用函数一样,使用运算符重载

d1.operator+=(10);
//调用Date& operator +=(int day)函数,在对象d1的基础上加10

4. const成员函数

在这里插入图片描述

我们来看下面的代码:

class Date
{
public:Date(int year = 2023, int month = 11, int day = 3){//简单的值拷贝_year = d._year;_month = d._month;_day = d._day;}void Print(){cout << _year << ';' << _month << ' ' << _day << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d1;const Date d2;d1.Print();		//Yesd2.Print();		//Notreturn 0;
}
//d2.Print()会报错:不能将“this”指针从“const Date”转换为“Date &”

这是因为:

我们之前提到过,引用不能涉及到权限的放大const Date d2对应的是const Date* this,而函数Print里的默认的是Date* this,这就涉及到了权限的放大。

因此,为了解决被const修饰的对像不能调用成员函数的问题,我们可以用const来修饰成员函数,这样,本质上成员函数的this指针就被const修饰了,从而也就可以被const对象调用。

4.1 const成员函数的声明

将一个成员函数变为const成员函数,只要在该函数声明的最后加上const修饰符即可

例如对于上面提到的Pinrt()成员函数,将其变为const成员函数即:

void Print() const
{cout << _year << ';' << _month << ' ' << _day << endl;
}

4.2 注意点

应该知道,引用不能涉及权限的放大,但是可以进行权限的平移和缩小。

因此:

  • const对象可以调用const成员函数
  • 非const对象也可以调用const成员函数

并不能说可以将所有的成员函数都声明为const成员函数,因为对于有些成员函数,它需要在函数内部修改对象的成员变量。

但是对于那些不需要修改对象成员变量的成员函数,建议都将其声明为cosnt,这样const对象和非const对象都能调用

5. 两个默认成员函数

运算符重载中也有两个成员函数,分别是:赋值=运算符重载和取地址&\const &运算符重载

5.1 赋值运算符重载

赋值运算符重载是类的默认成员函数

在这里插入图片描述

5.1.1 函数的声明

  • 因为赋值运算符重载是类的默认成员函数,因此必须声明在类的里面
  • =运算符的操作对象为2,因此该函数有两个形参。第一个形参为被隐藏的this指针,第二个形参就是要赋予值的对象,且该对象最好被const修饰
  • 为了支持连续赋值,函数的返回值应该是类类型的引用

例如,声明一个Date类的赋值运算符重载:

Date& operator=(const Date& d)
{//
}

5.1.2 函数的定义

应该清楚,赋值实际上也是一种拷贝。而拷贝又分为深拷贝和浅拷贝:

浅拷贝:

  • 浅拷贝又称值拷贝
  • 浅拷贝只是对成员变量值的简单复制,而不是复制指向的动态分配的资源(如堆内存)
  • 原对象和拷贝对象将共享相同的资源

深拷贝:

  • 深拷贝又称址拷贝
  • 相较于浅拷贝只是对成员变量值的简单赋值,深拷贝会复制对象的成员变量以及指向的资源,包括指针指向的数据
  • 这确保了原对象和拷贝对象拥有彼此独立但内容相同的资源副本

关于深浅拷贝更为清楚的解释请移步👉C++——拷贝构造

既然拷贝分为深浅拷贝,那么我们的赋值运算符重载也应该分为值拷贝、址拷贝这两种情况:

值拷贝:

例如对于Date类,里面没有指针指向空间资源,因此只需要对其成员变量进行简单复制操作

Date& operator=(const Date& d)
{//简单的值拷贝_year = d._year;_month = d._month;_day = d._day;return *this;
}

址拷贝:

例如对于Stack类,里面有一个指针用于指向栈存储的空间,因此需要进行深拷贝来创建一个和源对象内容相同但地址不同的空间

Stack& operator=(const Stack& st)
{_capacity = st._capacity;_top = st._top;//深拷贝_a = (int*)malloc(sizeof(int) * _capacity);if (nullptr == _a){perror("malloc");exit(-1);}memcpy(_a, st._a, sizeof(int) * _capacity);return *this;
}

5.1.3 赋值运算符重载和拷贝构造的区别

看完上面函数的定义,有小伙伴就肯定会有疑惑了:

这看起来二者之间没有什么区别嘛,为什么要做区分?

我们来看下面的例子:

class Date
{
public://构造Date(int year = 2023, int month = 11, int day = 3){_year = year;_month = month;_day = day;}//拷贝构造Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}//赋值运算符重载Date& operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;}
private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2 = d1;	//拷贝构造还是赋值运算符重载???Date d3;d3 = d2;	//拷贝构造还是赋值运算符重载???return 0;
}

各位认为,上面问题的答案是什么?让我们来进行调试:

在这里插入图片描述

可以得出结论:赋值运算符重载和拷贝构造的不同之处在于:

  • 拷贝构造注重的是构造,即用一个已经存在的对象来实例化构造一个新的对象
  • 赋值运算符重载注重的是赋值,即对两个已经存在的对象进行赋值操作

5.1.4 默认赋值运算符重载

和其他默认成员函数一样,如果自己没有声明和定义赋值运算符重载,编译器会自动生成一个

和拷贝构造一样,默认运算符重载只会对成员变量进行简单的值拷贝(浅拷贝),因此如果类的成员变量有指向内存空间的指针,仅依赖系统默认生成的赋值运算符重载是不够的,需要自己声明定义,来实现深拷贝

5.2 &和const &运算符重载

这两个函数都是类的默认成员函数

  • 他们的作用仅用于返回对象的地址
Date* operator&()
{return this;
}const Date* operator&() const
{return this;
}

这两个默认成员函数一般用编译器自动生成的默认&运算符重载即可,不需要自己声明和定义

6. 流插入<<、流提取>>运算符重载

在这里插入图片描述

通过查阅资料我们可以得知:coutostream类的对象,cinistream类的对象

extern ostream cout;
extern istream cin;

6.1 函数的声明

我们可以先看一个例子来推出这两个重载函数的返回值是什么:

cout << 10 << 20;

这串代码实现的是向屏幕连续输出两个数字10和20<<运算符的运算顺序应该是从左到右,而为了能够实现连续的cout,我们可以假象在执行完cout << 10后有生成了一个cout来完成cout << 20

在这里插入图片描述

而为了能够实现执行完cout << 10后又生成一个coutcout运算符重载的返回值就应该是ostream类的引用,即ostream &

同理,cin运算符重载的返回值就应该是istream &

接下来的问题是,这两个运算符重载应该放在类里面还是类外面呢?

如果声明在类里面:

class Date
{
public://构造Date(int year = 2023, int month = 11, int day = 3){_year = year;_month = month;_day = day;}ostream& operator<<(ostream& _cout){_cout << _year << ' ' << _month << ' ' << _day << endl;return _cout;}
private:int _year;int _month;int _day;
};

那当我们使用时:

int main()
{Date d1;cout << d1;return 0;
}
//就会报错:二元“<<”: 没有找到接受“Date”类型的右操作数的运算符(或没有可接受的转换)

这是因为,我们在前面就说过,对于二元运算符,第一个形参就是左操作数,第二个形参就是右操作数。而对于类的成员函数,this指针就是第一个参数,即左操作数。因此对于流插入运算符<<,左操作数就是d1,右操作数就是_cout

正确的写法应该为:

d1 << cout;

显然,这种写法的可读性是极差的。我们**应该想办法使_cout成为左操作数,this指针成为右操作数,**但是对于类的成员函数,形参的第一个都必定是指向对象的this指针,所以,为了达到要求,我们应该将<<>>运算符的重载声明定义在类的外面

即:

class Date
{
public://构造Date(int year = 2023, int month = 11, int day = 3){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << ' ' << d._month << ' ' << d._day << endl;return _cout;
}

我们将<<>>运算符的重载声明在类外面,可读性的问题是解决了,但是这样就访问不了被private修饰的成员变量了呀。

为了解决这个问题,我们可以使用友元函数friend

将非类成员函数的函数声明放在类里面,再在声明前面加上修饰符friend,这样这个函数就变成了友元函数。

  • 友元函数不是类的成员函数
  • 但是可以直接访问类的私有成员

例如,对于上面的代码:

class Date
{
public://构造Date(int year = 2023, int month = 11, int day = 3){_year = year;_month = month;_day = day;}friend ostream& operator<<(ostream& _cout, const Date& d);private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << ' ' << d._month << ' ' << d._day << endl;return _cout;
}

这样,我们就可以正确使用<<>>运算符重载了。

7. Date类的实现

class Date
{
public:// 获取某年某月的天数int GetMonthDay(int year, int month){int nums[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };if (month == 2 && (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)))return nums[month] + 1;elsereturn nums[month];}// 全缺省的构造函数Date(int year = 1900, int month = 1, int day = 1){if (year < 1 || month < 1 || month > 12 || day < 1 || day > GetMonthDay(year, month)){cout << "输入非法" << endl;exit(-1);}_year = year;_month = month;_day = day;}// 拷贝构造函数Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}// 赋值运算符重载Date& operator=(const Date& d){if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}// 日期+=天数Date& operator+=(int day){if (day < 0){return *this -= (-day);}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month > 12){_month = 1;_year++;}}return *this;}// 日期+天数Date operator+(int day){Date tmp = *this;tmp += day;return tmp;}// 日期-天数Date operator-(int day){	Date tmp = *this;tmp -= day;return tmp;}// 日期-=天数Date& operator-=(int day){if (day < 0)return *this += (-day);_day -= day;while (_day < 1){_month--;if (_month <= 0){_month = 12;_year--;}_day += GetMonthDay(_year, _month);}return *this;}// 前置++Date& operator++(){*this += 1;return *this;}// 后置++Date operator++(int){Date tmp = *this;*this += 1;return tmp;}// 后置--Date operator--(int){Date tmp = *this;*this -= 1;return tmp;}// 前置--Date& operator--(){*this -= 1;return *this;}// >运算符重载bool operator>(const Date& d){if (_year > d._year)return true;else if (_year == d._year && _month > d._month)return true;else if (_year == d._year && _month == d._month && _day > d._day)return true;elsereturn false;}// ==运算符重载bool operator==(const Date& d){return _year == d._year && _month == d._month && _day == d._day;}// >=运算符重载bool operator >= (const Date& d){return (*this == d) || (*this > d);}// <运算符重载bool operator < (const Date& d){	return !(*this >= d);}// <=运算符重载bool operator <= (const Date& d){return (*this == d) || (*this < d);}// !=运算符重载bool operator != (const Date& d){return !(*this == d);}// 日期-日期 返回天数int operator-(const Date& d){int flag = 1;if (!(*this >= d))flag = -1;Date cmp_big = *this >= d ? *this : d;Date cmp_small = *this < d ? *this : d;int count = 0;while (cmp_big != cmp_small){count++;++cmp_small;}return flag * count;}// 析构函数~Date(){//cout << "~Date()" << endl;}private:int _year;int _month;int _day;
};

7.1 对于部分代码的说明

  1. 注意代码的复用,这样可以少些许多代码,提高效率。

    例如:定义好+=、-=的运算符重载后,-、+运算符的重载就可以复用+=、-=的代码;定义好==、>的运算符重载后,其他比较运算符就可以复用==、>的运算符重载来实现,从而大幅减少了代码量。

  2. 注意前置++和后置++的运算符重载(前置--和后置--同理)

    由于C++规定,要构成运算符重载,运算符必须跟在operator后,因此当碰到前置++和后置++这种运算符相同(函数名相同)但函数实现的功能不同的情况时,就需要利用函数重载。我们可以在后置++的运算符重载函数的形参列表里加入一个形参,和前置++构成函数重载,这样就可以避免问题了。

相关文章:

C++——类和对象之运算符重载

运算符重载 本章思维导图&#xff1a; 注&#xff1a;本章思维导图对应的xmind文件和.png文件都已同步导入至”资源“ 文章目录 运算符重载[toc] 1. 运算符重载的意义2. 函数的声明2.1 声明运算符重载的注意事项 3. 函数的调用4. const成员函数4.1 const成员函数的声明4.2 注意…...

第二阶段第一章——面向对象

前言 学习了这么久Python&#xff08;呃其实也没多久差不多两周&#xff09;&#xff0c;可能有小伙伴说我废了&#xff0c;两周才学这么点&#xff0c;咋说呢&#xff0c;我曾经也是急于求成&#xff0c;做任何事情都是急于求成&#xff0c;比如我喜欢一个人我就想马上跟她在…...

Linux学习第33天:Linux INPUT 子系统实验(二):Linux 自带按键驱动程序的使用

Linux版本号4.1.15 芯片I.MX6ULL 大叔学Linux 品人间百味 思文短情长 本节笔记主要内容是学会如何使用Linux自带的按键驱动程序。 一、自带按键驱动程序源码简析 配置选项路径如下&#xff1a; -> Device Drivers ->…...

解决Visual Studio 2010 运行时屏幕一闪而过,无结果显示的问题

安装配置&#xff1a;Visual Studio 2010 软件安装教程&#xff08;附下载链接&#xff09;——计算机二级专用编程软件https://blog.csdn.net/W_Fe5/article/details/134218817?spm1001.2014.3001.5502 1、 我们在运行时会出现窗口一闪而过&#xff0c;这时候我们右键Test_1…...

C++(20):为[[nodiscard]]提供提示信息

C17中引入了[[nodiscard]]以对一些被忽略的函数返回值进行警告。 C(17)&#xff1a;[[nodiscard]]编译属性_[[nodiscard]] c-CSDN博客 C20可以为[[nodiscard]]提供一个可选的提示信息 [[nodiscard("cant ignore")]] int fi() {return 1; }int main() {fi();return 0…...

hi3518ev200 从sd卡启动rootfs

板卡为 hisi 的 hi3518ev200&#xff0c;16M RAM&#xff0c;64M Flash。板卡不支持从SD卡启动&#xff0c;但是由于Flash空间有限&#xff0c;很多应用都放不下&#xff0c;因此考虑把 rootfs 放到 SD 卡中。先从 Flash 中启动 kernel&#xff0c;然后再加载 SD 卡中的 rootfs…...

[BUUCTF NewStar 2023] week5 Crypto/pwn

最后一周几个有难度的题 Crypto last_signin 也是个板子题&#xff0c;不过有些人存的板子没到&#xff0c;所以感觉有难度&#xff0c;毕竟这板子也不是咱自己能写出来的。 给了部分p, p是1024位给了922-101位差两头。 from Crypto.Util.number import * flag b?e 655…...

使用seldom编写http接口用例

在编写接口用例的过程中&#xff0c;针对一个接口&#xff0c;往往只是参数不同&#xff0c;那么参数化就非常有必要了。 seldom 中参数化的用法非常灵活&#xff0c;这里仅介绍file_data() 的N种玩法。 二维列表 当参数比较简单时可以试试下面的方式。 参数化数据 {"…...

Redis中Hash类型的命令

目录 哈希类型的命令 hset hget hexists hdel hkeys hvals hgetall hmget hlen hsetnx hincrby hincrbyfloat 内部编码 Hash类型的应用场景 作为缓存 哈希类型和关系型数据库的两点不同之处 缓存方式对比 Redis自身已经是键值对的结构了,Redis自身的键值对就…...

Java 函数式编程

1.Lambda 1.1 格式 JDK 从 1.8 版本开始支持 Lambda 表达式&#xff0c;通过 Lambda 表达式我们可以将一个函数作为参数传入方法中。在 JDK 1.8 之前&#xff0c;我们只能通过匿名表达式来完成类似的功能&#xff0c;但是匿名表达式比较繁琐&#xff0c;存在大量的模板代码&…...

类的成员函数总结

前言&#xff1a; 如果一个类中什么成员都没有&#xff0c;简称为空类。 空类中真的什么都没有吗&#xff1f;并不是&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。 默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生成的…...

java高级之单元测试、反射

1、Junit测试工具 Test定义测试方法 1.被BeforeClass标记的方法,执行在所有方法之前 2.被AfterCalss标记的方法&#xff0c;执行在所有方法之后 3.被Before标记的方法&#xff0c;执行在每一个Test方法之前 4.被After标记的方法&#xff0c;执行在每一个Test方法之后 public …...

MSQL系列(十三) Mysql实战-left/right/inner join 使用详解及索引优化

Mysql实战-left/right/inner join 使用详解及索引优化 前面我们讲解了BTree的索引结构&#xff0c;也详细讲解下Join的底层驱动表 选择原理&#xff0c;今天我们来了解一下为什么会出现内连接外连接&#xff0c;两种连接方式&#xff0c;另外实战一下内连接和几种最常用的join…...

前端面试题之HTML篇

1、src 和 href 的区别 具有src的标签有&#xff1a;script、img、iframe 具有href的标签有&#xff1a;link、a 区别 src 是source的缩写。表示源的意思&#xff0c;指向资源的地址并下载应用到文档中。会阻塞文档的渲染&#xff0c;也就是为什么js脚本放在底部而不是头部的…...

Django ORM:数据库操作的Python化艺术

Django的对象关系映射器&#xff08;ORM&#xff09;是其核心功能之一&#xff0c;允许开发者使用Python代码来定义、操作和查询数据库。这篇文章将带你深入了解Django ORM的强大之处&#xff0c;从基本概念到高级查询技巧&#xff0c;提供丰富的示例帮助你掌握使用Django ORM进…...

react受控组件与非受控组件

React中的组件可以分为受控组件和非受控组件&#xff1a; 受控组件&#xff1a;受控组件是指组件的值受到React组件状态的控制。通常在组件中&#xff0c;我们会通过state来存储组件的值&#xff0c;然后再将state的值传递给组件的props&#xff0c;从而实现组件的双向数据绑定…...

小米产品面试题:淘宝为何需要确认收货?京东为何不需要?

亲爱的小米粉丝们&#xff0c;大家好&#xff01;我是小米&#xff0c;一个热爱技术、热衷于分享的小编。今天&#xff0c;我要和大家聊聊一个有趣的话题&#xff1a;为什么淘宝购物需要确认收货&#xff0c;而京东不需要&#xff1f;这可是一个让很多人纳闷的问题&#xff0c;…...

(1)上位机底部栏 UI如何设置

上位机如果像设置个多页面切换&#xff1a; 位置&#xff1a; 代码如下&#xff1a; "tabBar": {"color": "black","selectedColor": "#d43c33","borderStyle":"black","backgroundColor": …...

中国多主数据库:压强投入,期待破茧

拿破仑曾说&#xff1a;“战争的艺术就是在某一点上集中最大优势兵力”&#xff0c;强调了力量集中的重要性。 如今&#xff0c;国际形势风云变幻&#xff0c;西方世界对中国的围剿不再仅仅体现在军事和地缘政治上&#xff0c;而更多表现在经济与科技上。在科技领域&#xff0…...

JavaScript在ES6及后续新增的常用新特性

JavaScript经历了不同标本的迭代&#xff0c;在不断完善中会添加不同的新特性来解决前一个阶段的瑕疵&#xff0c;让我们开发更加便捷与写法更加简洁&#xff01; 1、箭头函数&#xff1a; 箭头函数相比传统的函数语法&#xff0c;具有更简洁的语法、没有自己的this值、不会绑…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

Caliper 配置文件解析:config.yaml

Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

群晖NAS如何在虚拟机创建飞牛NAS

套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

【堆垛策略】设计方法

堆垛策略的设计是积木堆叠系统的核心&#xff0c;直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法&#xff0c;涵盖基础规则、优化算法和容错机制&#xff1a; 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则&#xff1a; 大尺寸/重量积木在下&#xf…...

【51单片机】4. 模块化编程与LCD1602Debug

1. 什么是模块化编程 传统编程会将所有函数放在main.c中&#xff0c;如果使用的模块多&#xff0c;一个文件内会有很多代码&#xff0c;不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里&#xff0c;在.h文件里提供外部可调用函数声明&#xff0c;其他.c文…...

初探用uniapp写微信小程序遇到的问题及解决(vue3+ts)

零、关于开发思路 (一)拿到工作任务,先理清楚需求 1.逻辑部分 不放过原型里说的每一句话,有疑惑的部分该问产品/测试/之前的开发就问 2.页面部分(含国际化) 整体看过需要开发页面的原型后,分类一下哪些组件/样式可以复用,直接提取出来使用 (时间充分的前提下,不…...

基于微信小程序的作业管理系统源码数据库文档

作业管理系统 摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和微信小程序来完成对系统的…...