类和对象【5】日期类的实现

news2024/11/28 6:45:15

全文目录

  • 引言
  • 实现日期类
    • 概述
    • 默认成员函数
      • 构造函数
      • 析构函数
      • 拷贝构造
      • 赋值重载
    • 功能运算符重载
      • 日期间的比较
      • 日期+=与+天数
      • 日期-=与-天数
      • 日期前置++与后置++
      • 日期前置- -与后置- -
      • 日期 - 日期
    • 输入输出重载(友元)
  • 代码总览
    • 头文件
    • 源文件
    • main函数
  • 总结

引言

类和对象1(初识)
类和对象2(默认成员函数)
类和对象3(初始化列表)
类和对象4(static、const、友元)
在了解了类和对象的基础知识后,我们就可以简单实现一个日期类(前期的知识介绍链接如上,一些基础知识本文就不过多赘述):

实现日期类

概述

我们可以先来看一下网络上找到的日期计算器的功能:
在这里插入图片描述
可以实现计算两个日期之差,日期加减天数等。

在学习类和对象之前,我们会将日期的年月日存储在结构体中,然后通过封装函数来实现对这个日期结构体的操作;
但是现在,我们就可以将日期封装为类类型的属性,对日期类的操作封装为类的方法,以方便我们使用。

当然,为了实现上面提到的两个功能,我们需要实现判段两个日期是否相等,比较两个日期等方法,当然也需要将日期打印出来的方法。接下来就会一一实现:

我们首先定义一个类类型:

class Date
{
private:
	int _year;
	int _month;
	int _day;
};

默认成员函数

首先来实现4个默认成员函数

构造函数

这个日期类中只有内置类型,所以编译器生成的无参的默认成员函数不能实现其初始化。我们可以实现一个全缺省的默认构造函数,这样既可以不传参定义类对象,也可以传参:

// 全缺省的构造函数
Date::Date(int year, int month, int day)
    : _year(year)
    , _month(month)
    , _day(day)
{}

在初始化列表中实现对成员变量的初始化。

析构函数

日期类中其实并没有动态开辟的资源,所以编译器自动生成的析构函数就已经足够,但是这里还是实现一下,可以在析构函数中将成员变量置0:

// 析构函数
Date::~Date()
{
    _year = 0;
    _month = 0;
    _day = 0;
}

拷贝构造

拷贝构造函数是构造函数的重载,参数为类对象的引用:

// 拷贝构造函数
// d2(d1)
Date::Date(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
}

使用const修饰参数,可以使const对象也可以作为参数对新的类对象赋值。

赋值重载

赋值运算符重载就是operator=的函数重载。显式的参数为const Date&即可以传const修饰的对象:

// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& Date::operator=(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
    return *this;
}

在函数中将该对象(this指针指向的)的成员变量赋值为d中的成员变量即可。

需要注意的是,为了实现连续赋值,这个函数的返回值为类类型的引用,返回*this
例如将几个内置类型变量连续赋值:

a = b = c = d;

在这样的代码中,就是d给c赋值的结果给b赋值,结果再给a赋值。
所以对于赋值运算符重载,这个函数返回的就应该是=前面的操作数,即第一个参数的引用,即返回*this

功能运算符重载

有了默认成员函数后,我们继续实现成员函数:

日期间的比较

日期的比较可以实现如下的重载:==、!=、>、>=、<、<=

这些函数的参数列表应该都是相同的,都是一个隐式的this指针与一个类的引用Date&
返回值都是bool,如果表达式成立就返回true,否则返回false。

但是这类函数中都不需要改变对象的值,所以可以对this指针指向的对象与类对象的引用都用const修饰:

//==重载举例:
bool operator==(const Date& d) const;

实现时,在函数中通过判断两个对象中的成员变量得出两个日期的大小关系了:
==运算符重载

// ==运算符重载
bool Date::operator==(const Date& d)const
{
    if ((_year == d._year)
        && (_month == d._month)
        && (_day == d._day))
    {
        return true;
    }
    else
    {
        return false;
    }
}
  1. !=运算符重载
// !=运算符重载
bool Date::operator!=(const Date& d)const
{
    if (!(*this == d))
    {
        return true;
    }
    return false;
}
  1. >运算符重载
// >运算符重载
bool Date::operator>(const Date& d)const
{
    if (_year > d._year)
    {
        return true;
    }
    if (_year == d._year && _month > d._month)
    {
        return true;
    }
    if (_year == d._year && _month == d._month && _day > d._day)
    {
        return true;
    }
    return false;
}
  1. >=运算符重载
// >=运算符重载
bool Date::operator>=(const Date& d)const
{
    if (*this > d || *this == d)
    {
        return true;
    }
    return false;
}
  1. <运算符重载
// <运算符重载
bool Date::operator<(const Date& d)const
{
    if (_year < d._year)
    {
        return true;
    }
    if (_year == d._year && _month < d._month)
    {
        return true;
    }
    if (_year == d._year && _month == d._month && _day < d._day)
    {
        return true;
    }
    return false;
}
  1. <=运算符重载
// <=运算符重载
bool Date::operator<=(const Date& d)const
{
    if (*this < d || *this == d)
    {
        return true;
    }
    return false;
}

日期+=与+天数

  1. 日期+=天数

日期+=天数,即计算该日期对象(隐式的this指向的)在某天数后的日期是哪一天,返回对象的引用。+=操作符,显然是会改变该日期对象的成员变量的,所以不能用const修饰

Date& operator+=(int day);

在实现时,可以先给该日期对象的_day成员加上day
_day的值大于当前_month的值时,_day减去当前月的天数,然后_month加1(向后走一月);
_month的值大于12,则重置为1,_year加1(向后走一年);
直到_day的值小于当前月的天数为止;
最后返回*this的引用

我们可以再封装一个函数来获取某月的天数(通过数组的方式存储12个月的天数,返回对应月的天数即可):

// 获取某年某月的天数(用于日期加减天数)
 int Date::GetMonthDay(int year, int month)
{
    int monthdays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    if ((month == 2) && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
    {
        monthdays[month] = 29;
    }
    return monthdays[month];
}

然后就可以实现+=运算符重载:
需要注意的是,传参的天数day可以为负数,即表示该日期减-day,此时调用嗲用-=即可(马上就会实现)

// 日期+=天数
Date& 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)
        {
            _year++;
            _month = 1;
        }
    }
    return *this;
}
  1. 日期+天数

日期+天数,是不能修改该日期类的日期的,所以可以为this指针指向的对象加const修饰:

Date operator+(int day)const;

在函数中,创建一个临时日期类对象temp,并用*this对其初始化(拷贝构造);
然后对temp+=day;,即调用上面实现的+=重载;
最后返回temp
需要注意的是,这里的temp在出作用域后就会销毁,所以这里的返回值必须为值,而非返回引用(虽然传值返回会调拷贝构造)

// 日期+天数
Date Date::operator+(int day)const
{
    Date temp(*this);//拷贝构造
    temp += day;//复用+=运算符重载
    return temp;//返回临时值,不改变*this的值
}

日期-=与-天数

  1. 日期-=天数

日期-=天数的实现与+=类似:
先给_day减去day
如果减去day_day的值小于0,则_day加上当前月的上一个月(_month-1)的天数;
_month的值小于0,_month置为12,_year的值减1;
直到_day的值大于0为止;
最后返回*this的引用

// 日期-=天数
Date& Date::operator-=(int day)
{
    if (day < 0)
    {
        return *this += -day;
    }
    _day -= day;
    while (_day < 1)
    {
        _month--;
        _day += GetMonthDay(_year, _month);//如果--后的_month为0,函数返回0,不影响结果

        if (_month <= 0)
        {
            _year--;
            _month = 13;
        }
    }
    return *this;
}

在实现时需要注意的是:
_month的值为1时,_day要加上(_month-1)月的天数,此时传给GetMonthDay的就是0,但是由于我们在实现GetMonthDay时,月份数组中下标为0的数据为0,_day-0_day没有影响,所以不影响最终的结果;
_day小于0时,就调用+= -day的方式来解决即可。

  1. 日期 - 天数

日期-天数的实现与+类似,需要创建临时对象temp,并且必须返回值而不能返回引用

// 日期-天数
Date Date::operator-(int day)const
{
    Date temp;
    temp -= day;
    return temp;
}

日期前置++与后置++

++就是+=1,这很容易理解,所以在这个函数中,只需要调用上面重载来+=1即可。

需要注意的是,前置++与后置++的区别:前置++在+=1后,表达式的值为+1后的值;而后置++在+=1后,表达式的值为+1前的值。

在++中,操作数就是类对象,前置++版本重载的返回值应该为+1后的引用;后置版本的返回值应该为对象在递增前的值

我们只需要想办法区分operator的参数列表来实现重载即可:
对于两个操作数的操作符运算符重载,函数的第一个参数对应左操作数,第二个参数对应右操作数。例如==的重载:bool operator==(const Date& d);的第一个参数为隐式的this,第二个参数为const Date& d。调用这个重载函数时可以:d1 == d2;这个调用就相当于d1.operator==(d2);

  1. 前置++

前置++可以只隐式的传递this指针作为第一个参数,它就对应着前置++的操作数;
由于返回递增后的日期对象,所以返回对象的引用即可:

// 前置++
Date& Date::operator++()
{
    *this += 1;
    return *this;
}

我们在使用前置++时,就相当于调用这个重载函数:d.operator++();

  1. 后置++

后置++的实现为了与前置++区分,参数列表中除了隐式的this指针,还可以有一个不被使用的int。*this对应着后置++的第一个操作数,int对应着第二个操作数(但是这里的int只做区分意义,并不使用);
由于返回递增前的日期对象,所以需要创建临时对象temp,用 *this 初始化,原对象递增后返回temp即可。这里需要值返回而非引用返回(原因与前面一致):

// 后置++
Date Date::operator++(int)
{
    Date temp(*this);
    *this += 1;
    return temp;
}

使用后置++时,就相当于调用这个重载函数:d.operator++(0);

日期前置- -与后置- -

前置 - - 与后置 - - 的实现与区分思路与++类似,在函数中使用-=,并且以额外的int形参区分

  1. 前置 - -
// 前置--
Date& Date::operator--()
{
    *this -= 1;
    return *this;
}

引用返回递减后的对象,使用时相当于:d.operator--();

  1. 后置 - -
// 后置--
Date Date::operator--(int)
{
    Date temp(*this);
    *this -= 1;
    return *this;
}

值返回递减前的对象,使用时相当于:d.operator--(0);

日期 - 日期

日期 - 日期即重载-,返回两个日期之间相差多的天数。

参数列表有两个,即隐式的this指针,与类对象的引用。由于在进行计算两日期之间天数时不会改变日期对象,所以对 *this 与对象的引用都用const修饰(与前面比较运算符重载时相同,这里不再赘述);
返回值为int,表示相差的天数:

int operator-(const Date& d)const;

实现这个函数时,我们可以直接通过小日期递增,并且记录递增的次数,知道两个日期相等,返回计数器变量的值。
需要注意的是:不能改变原对象的值,所以创建临时对象temp来递增计数

// 日期-日期 返回天数
int Date::operator-(const Date& d)const
{
    int day = 0;
    Date temp(*this);
    if (temp > d)
    {
        while (temp != d)
        {
            --temp;
            day++;
        }
    }
    else
    {
        while (temp != d)
        {
            ++temp;
            day--;
        }
    }
    return day;
}

输入输出重载(友元)

在实现了上面这些成员函数后,类对象的加、减、乘、除、比较等都可以像内置类型一样使用,大大提高了便利与可读性,那么能不能对输入与输出的运算符>><<也进行重载呢?当然是可以的:

cincout是标准输入与标准输出对象,使用cin >> 可以从标准输入流中读取数据;cout << 可以将数据打印在标准输出流中。它们的类类型分别是istreamostream

有了这样的知识,我们只要将>>操作符左边的操作数对应到cin,右边的操作数对应到要输入的类对象,就可以实现>>的重载;同理,<<左边的操作数对应为cout,右边的操作数对应为要打印的类对象,就可以实现<<的重载。
如此,>>重载的第一个参数类型应该为istream&,第二个参数类型应为Date&<<重载的第一个参数类型应为ostream&,第二个参数类型应为const Date&

但是,对于类的成员函数,第一个参数一定是固定的隐式传参的this指针,这就导致了对于成员函数而言,不可能实现上面的传参方式。

要想实现上面的传参方式,就必须是非成员函数,并且要能在函数中访问成员变量。在这样的需求下,我们可以使用friend来声明一个外部函数作为该类的友元函数,这样就可以既没有隐式的this,也能访问成员变量了;
为了实现连续的输入输出,表达式的值应为流,所以在实现重载时,函数的返回值为istream&ostream&

//>>重载
istream& operator>>(istream& in,  Date& d)
{
    int year = 0;
    int month = 0;
    int day = 0;
    in >> year >> month >> day;
    if (month < 1 || month>12 || day<1 || day>Date::GetMonthDay(year, month))
    {
        cout << "输入错误" << endl;
        assert(0);
    }
    else
    {
        d._year = year;
        d._month = month;
        d._day = day;
    } 
    return in;
}
//<<重载
ostream& operator<<(ostream& out, const Date& d)
{
    if (d._month < 1 || d._month>12 || d._day<1 || d._day>Date::GetMonthDay(d._year, d._month))
    {
        cout << "输入错误" << endl;
    }
    out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
    return out;
}

当然还需要在类内部加上friend声明。

到此,所有日期类的成员函数就实现完了,总的代码就在后面,我们也可以写一个程序来测试一下这个日期类。

代码总览

头文件

//头文件

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

class Date
{
	//友元输入输出
	friend istream& operator>>(istream& in, Date& d);
	friend ostream& operator<<(ostream& out, const Date& d);
public:
	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1);

	// 拷贝构造函数
    // d2(d1)
	Date(const Date& d);	
	
	// 赋值运算符重载
    // d2 = d3 -> d2.operator=(&d2, d3)
	Date& operator=(const Date& d);

	// 析构函数
	~Date();	
	
	// 获取某年某月的天数
	static int GetMonthDay(int year, int month);

	// 日期+=天数
	Date& operator+=(int day);
	// 日期+天数
	Date operator+(int day)const;
	// 日期-=天数
	Date& operator-=(int day);
	// 日期-天数
	Date operator-(int day)const;
	// 前置++
	Date& operator++();
	// 后置++
	Date operator++(int);
	// 前置--
	Date& operator--();
	// 后置--
	Date operator--(int);
	// >运算符重载
	bool operator>(const Date& d)const;
	// ==运算符重载
	bool operator==(const Date& d)const;
	// >=运算符重载
	bool operator >= (const Date& d)const;
	// <运算符重载
	bool operator < (const Date& d)const;
	// <=运算符重载
	bool operator <= (const Date& d)const;
	// !=运算符重载
	bool operator != (const Date& d)const;
	// 日期-日期 返回天数
	int operator-(const Date& d)const;

	//打印
	void printDate()const;
private:
	int _year;
	int _month;
	int _day;
};
istream& operator>>(istream& in, Date& d);
ostream& operator<<(ostream& out, const Date& d);

源文件

//源文件
#include"data.h"

// 全缺省的构造函数
Date::Date(int year, int month, int day)
    : _year(year)
    , _month(month)
    , _day(day)
{}

// 拷贝构造函数
// d2(d1)
Date::Date(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
}

// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& Date::operator=(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
    return *this;
}

// 析构函数
Date::~Date()
{
    _year = 0;
    _month = 0;
    _day = 0;
}

// 获取某年某月的天数(用于日期加减天数)
 int Date::GetMonthDay(int year, int month)
{
    int monthdays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
    if ((month == 2) && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
    {
        monthdays[month] = 29;
    }
    return monthdays[month];
}

// 日期+=天数
Date& 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)
        {
            _year++;
            _month = 1;
        }
    }
    return *this;
}
// 日期+天数
Date Date::operator+(int day)const
{
    Date temp(*this);//拷贝构造
    temp += day;//复用+=运算符重载
    return temp;//返回临时值,不改变*this的值
}
// 日期-=天数
Date& Date::operator-=(int day)
{
    if (day < 0)
    {
        return *this += -day;
    }
    _day -= day;
    while (_day < 1)
    {
        _month--;
        _day += GetMonthDay(_year, _month);//如果--后的_month为0,函数返回0,不影响结果

        if (_month <= 0)
        {
            _year--;
            _month = 13;
        }
    }
    return *this;
}
// 日期-天数
Date Date::operator-(int day)const
{
    Date temp;
    temp -= day;
    return temp;
}
// 前置++
Date& Date::operator++()
{
    *this += 1;
    return *this;
}
// 后置++
Date Date::operator++(int)
{
    Date temp(*this);
    *this += 1;
    return temp;
}
// 前置--
Date& Date::operator--()
{
    *this -= 1;
    return *this;
}
// 后置--
Date Date::operator--(int)
{
    Date temp(*this);
    *this -= 1;
    return *this;
}
// ==运算符重载
bool Date::operator==(const Date& d)const
{
    if ((_year == d._year)
        && (_month == d._month)
        && (_day == d._day))
    {
        return true;
    }
    else
    {
        return false;
    }
}
// >运算符重载
bool Date::operator>(const Date& d)const
{
    if (_year > d._year)
    {
        return true;
    }
    if (_year == d._year && _month > d._month)
    {
        return true;
    }
    if (_year == d._year && _month == d._month && _day > d._day)
    {
        return true;
    }
    return false;
}
// >=运算符重载
bool Date::operator>=(const Date& d)const
{
    if (*this > d || *this == d)
    {
        return true;
    }
    return false;
}
// <运算符重载
bool Date::operator<(const Date& d)const
{
    if (_year < d._year)
    {
        return true;
    }
    if (_year == d._year && _month < d._month)
    {
        return true;
    }
    if (_year == d._year && _month == d._month && _day < d._day)
    {
        return true;
    }
    return false;
}
// <=运算符重载
bool Date::operator<=(const Date& d)const
{
    if (*this < d || *this == d)
    {
        return true;
    }
    return false;
}
// !=运算符重载
bool Date::operator!=(const Date& d)const
{
    if (!(*this == d))
    {
        return true;
    }
    return false;
}
// 日期-日期 返回天数
int Date::operator-(const Date& d)const
{
    int day = 0;
    Date temp(*this);
    if (temp > d)
    {
        while (temp != d)
        {
            --temp;
            day++;
        }
    }
    else
    {
        while (temp != d)
        {
            ++temp;
            day--;
        }
    }
    return day;
}
//打印
void Date::printDate()const
{
    cout << _year << " " << _month << " " << _day << endl;
}

istream& operator>>(istream& in,  Date& d)
{
    int year = 0;
    int month = 0;
    int day = 0;
    in >> year >> month >> day;
    if (month < 1 || month>12 || day<1 || day>Date::GetMonthDay(year, month))
    {
        cout << "输入错误" << endl;
        assert(0);
    }
    else
    {
        d._year = year;
        d._month = month;
        d._day = day;
    } 
    return in;
}
ostream& operator<<(ostream& out, const Date& d)
{
    if (d._month < 1 || d._month>12 || d._day<1 || d._day>Date::GetMonthDay(d._year, d._month))
    {
        cout << "输入错误" << endl;
    }
    out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
    return out;
}

main函数

//main函数
int main()
{
    Date d1;
    cin >> d1;
    cout << d1;

    Date d2(2023, 5, 20);
    cout << d2;
    cout << d2 - d1 << "天" << endl;
    return 0;
}

在这里插入图片描述

总结

到此,关于日期类的实现就介绍完了。通过实现日期类,相信大家对类和对象有了更深的了解
同时,类和对象的基础知识也介绍完了
C++之旅还在继续,欢迎大家持续关注哦!!!

如果大家认为我对某一部分没有介绍清楚或者某一部分出了问题,欢迎大家在评论区提出

如果本文对你有帮助,希望一键三连哦

C++之路才刚刚开始,我们一起加油吧!

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

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

相关文章

详解Java异常和异常面试题(上)

1.异常的体系结构 2.从程序执行过程&#xff0c;看编译时异常和运行时异常 编译时异常&#xff1a;执行javac.exe命名时&#xff0c;可能出现的异常 运行时异常&#xff1a;执行java.exe命名时&#xff0c;出现的异常 1.运行时异常  是指编译器不要求强制处置的异常。一般是…

网络安全:信息收集专总结【社会工程学】

前言 俗话说“渗透的本质也就是信息收集”&#xff0c;信息收集的深度&#xff0c;直接关系到渗透测试的成败&#xff0c;打好信息收集这一基础可以让测试者选择合适和准确的渗透测试攻击方式&#xff0c;缩短渗透测试的时间。 一、思维导图 二、GoogleHacking 1、介绍 利用…

HVV常问的Web漏洞(护网蓝初面试干货)

目录 1、SQL注入 &#xff08;1&#xff09;原理 &#xff08;2&#xff09;分类 &#xff08;3&#xff09;防御 2、XSS &#xff08;1&#xff09;原理 &#xff08;2&#xff09;分类 3、中间件&#xff08;解析漏洞&#xff09; &#xff08;1&#xff09;IIS6.X …

【AI实战】开源大语言模型LLMs汇总

【AI实战】开源大语言模型LLM汇总 大语言模型开源大语言模型1、LLaMA2、ChatGLM - 6B3、Alpaca4、PandaLLM5、GTP4ALL6、DoctorGLM &#xff08;MedicalGPT-zh v2&#xff09;7、MedicalGPT-zh v18、Cornucopia-LLaMA-Fin-Chinese9、minGPT10、InstructGLM11、FastChat12、Luot…

在线原型设计工具推荐

原型设计是每个产品经理必备的基本技能。 本文从即时设计原型设计的步骤开始&#xff0c;帮助您快速使用即时设计制作高还原度、丰富互动的产品原型。 利用即时设计进行原型设计的优势 快速启动原型设计工作 借助即时设计内置设计系统和社区资源&#xff0c;包括大量原型设…

Hive执行计划之什么是hiveSQL向量化模式及优化详解

目录 文章目录 1.什么是hive向量化模式2.Hive向量化模式支持的使用场景2.1 hive向量化模式使用前置条件2.2 向量模式支持的数据类型2.3 向量化模式支持的函数 3.如何查看hiveSQL向量化运行信息3.1 explain vectorization only只查询向量化描述信息内容3.2 explain vectorizati…

javaScript蓝桥杯---JSON 生成器

目录 一、介绍二、准备三、目标四、代码五、完成 一、介绍 JSON 已经是大家必须掌握的知识点&#xff0c;JSON 数据格式为前后端通信带来了很大的便利。在开发中&#xff0c;前端开发工程师可以借助于 JSON 生成器快速构建一个 JSON 用来模拟数据。 本题请你开发一个简易的 J…

chatgpt赋能python:Python快速安装库

Python快速安装库 Python作为一种功能强大且易于学习的编程语言&#xff0c;已经成为许多开发人员的首选。在Python中&#xff0c;库是重要的一部分&#xff0c;它们提供了各种功能和工具来简化开发过程。安装这些库的过程可能会比较繁琐&#xff0c;但我们可以通过一些简单的…

PHP的学习--Traits新特性

自 PHP 5.4.0 起&#xff0c;PHP 实现了代码复用的一个方法&#xff0c;称为 traits。 Traits 是一种为类似 PHP 的单继承语言而准备的代码复用机制。Trait 为了减少单继承语言的限制&#xff0c;使开发人员能够自由地在不同层次结构内独立的类中复用方法集。Traits 和类组合的…

博客系统测试用例设计之自动化测试

测试用例设计之自动化测试 &#x1f337; 一 测试用例设计&#x1f33a; 1 功能测试&#x1f338; &#xff08;1&#xff09;登录功能&#x1f338; &#xff08;2&#xff09;列表页功能&#x1f338; &#xff08;3&#xff09;编辑博客功能&#x1f338; &#xff08;4&…

大厂设计师都在用的9个灵感工具

每一件伟大的设计作品都离不开设计师灵感的爆发。设计师有很多灵感来源&#xff0c;比如精美的摄影图片、酷炫的网站设计、APP的特色功能、友好的用户体验动画&#xff0c;或者一篇文章。 设计师每天都需要收集灵感&#xff0c;把灵感收集当成日常生活。在这篇文章中&#xff…

自动化测试工具比较:Selenium vs. Cypress

简介 Selenium是一个广泛应用的测试自动化工具&#xff0c;支持多种编程语言和浏览器。它使用WebDriver协议与浏览器进行通信&#xff0c;可以模拟用户在浏览器中的交互行为。Cypress是一个相对较新的测试自动化工具&#xff0c;它专注于现代Web应用程序的测试&#xff0c;并提…

LarkXR知识库 | 开发者社区FAQ合集(二)

LarkXR是一套基于GPU云化、图形容器、音视频实时编解码、网络传输优化等核心技术的通用型实时云渲染解决方案&#xff0c;帮助XR领域企业级用户及开发者快速搭建XR应用上云通道&#xff0c;使其在各类智能终端上流畅的运行、使用及传播。 平行云开发者社区上线以来&#xff0c…

Git基本知识

Git基本知识 1、Git 资料参考 Git 官网&#xff1a;https://book.git-scm.com/ Git 完整命令手册地址&#xff1a;http://git-scm.com/docs Git 中文文档&#xff1a;https://git-scm.com/book/zh/v2 2、Git安装 Git 各平台安装包下载地址为&#xff1a; http://git-scm…

F407标准库之定时器触发AD转换

关于ADC转换&#xff0c;正点原子的标准库开发中讲的是&#xff1a;软件触发一次转换&#xff0c;然后获取一个数据&#xff0c;没提及外部触发&#xff0c;也没提及ADC中断。 如果要多次读取数据&#xff0c;可以通过循环延时来实现。 这种情况就是通过多次调用&#xff0c;轮…

中国电子学会2023年05月份青少年软件编程Scratch图形化等级考试试卷三级真题(含答案)

2023-05 Scratch三级真题 分数&#xff1a;100 题数&#xff1a;38 测试时长&#xff1a;60min 一、单选题(共25题&#xff0c;共50分) 1. 关于变量&#xff0c;下列描述错误的是&#xff1f;&#xff08;A &#xff09;&#xff08;2分&#xff09; A.只能建一个变量 …

【CANoe】CAPL如何检测周期性报文

文章目录 一、实例1、新建工程2、增加两个 Module3、选择在线模式(Online Mode)仿真总线(Simulated Bus)4、配置CAPL Test Moduletest.can代码如下&#xff1a; 5、配置CAN IG(发送周期报文0x101)6、测试结果 二、核心代码三、CAPL函数详解截图参考&#xff1a; 一、实例 以下…

浅谈这些年如何被MDK, IAR, GCC和厂家SDK版本兼容性“蹂躏”, 一代版本一代坑

原创文章&#xff0c;转载请注明出处&#xff1a;https://www.armbbs.cn/forum.php?modviewthread&tid119562 版本迭代是嵌入式开发永久的痛&#xff0c;这么多年不知道浪费了多少时间在版本迭代上。 部分系统组件还好点&#xff0c;有个LTS长期支持版&#xff0c;而厂家…

侧信道攻击:SPA / DPA

参考资料&#xff1a;Cryptographic Engineering, by Cetin Kaya Ko, Editor Springer. 文章目录 Side-Channel AnalysisTiming AnalysisSample Power AnalysisDifferential Power Analysis其他攻击 对抗方法 Side-Channel Analysis 对于密码算法的攻击手段&#xff0c;往往是…

【LoRaWAN】单播与组播multicast调试记录

本文主要记录 【LoRaWAN】单播与组播multicast调试过程的问题 2023.06.09 &#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是喜欢记录零碎知识点的小菜鸟。&#x1f60e;&#x1f4dd; 个人主页&#xff1a;[欢迎访问我的 Ethernet_Comm 博客…