【C++实战项目】Date日期类 --- 运算符重载的深入探索

在这里插入图片描述

📷 江池俊:个人主页
🔥 个人专栏:✅C++那些事儿 ✅Linux技术宝典
🌅 此去关山万里,定不负云起之望


在这里插入图片描述

文章目录

    • 引言
    • 一、为什么需要运算符重载?
    • 二、日期类的实现
      • 1. 基本框架
      • 2. 预备工作
      • 3. Date 类中六大默认成员函数的使用
        • 3.1 全缺省的构造函数
        • 3.2 拷贝构造函数
        • 3.3 析构函数
        • 3.4 赋值运算符重载
        • 3.5 const 成员函数
        • 3.6 取地址操作符重载和const取地址操作符重载
      • 4. 运算符重载
        • 4.1 += 和 + 运算符重载
        • 4.2 -= 和 - 运算符重载
        • 4.3 前置++ 和 后置++ 运算符重载
        • 4.4 前置-- 和 后置-- 运算符重载
        • 4.5 > 和 == 运算符重载
        • 4.6 >= 、< 、<= 和 != 运算符重载
        • 4.7 日期-日期
        • 4.8 流插入 << 和 流提取 >> 运算符重载
    • 5. 日期类源码
      • 5.1 Date.h文件
      • 5.2 Date.cpp 文件
    • 总结


引言

在C++编程中,运算符重载是一种强大的功能,它允许我们为自定义的数据类型定义运算符的行为。这种特性在创建像日期(Date)这样的类时尤其有用,因为它允许我们更自然、更直观地操作这些类的实例。通过日期类我们还能够实现一个简单的日期时间计数器的功能,想必大家都很期待接下来的内容。

在这里插入图片描述

在本篇博客中,我们将深入探索如何为Date类重载运算符,并了解其中的一些最佳实践和潜在陷阱。

Date.h文件下放日期类的声明代码,Date.c文件下放日期类的实现代码


一、为什么需要运算符重载?

运算符重载可以让我们使用更直观、更自然的方式来操作日期。

在创建日期类时,我们可能希望执行如下操作:

  • 对两个日期进行加法运算以得到一个新的日期(例如,将5天加到今天的日期上)。
  • 比较两个日期以确定哪个日期更早或更晚。
  • 从一个日期中减去另一个日期以得到它们之间的时间差。
  • 等等…

为了实现这些操作,我们需要为Date类重载相应的运算符,如+、-、<等。


二、日期类的实现

1. 基本框架

class Date
{
public:
	// 获取某年某月的天数
	int GetMonthDay(int year, int month) const;
	// 检查日期是否合法
	bool CheckInvalid();

	// 全缺省的构造函数
	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();

	// ======== 有关日期计算的运算符重载 ========
	// 日期+=天数
	Date& operator+=(int day);
	// 日期+天数
	Date operator+(int day);
	// 日期-天数
	Date operator-(int day);
	// 日期-=天数
	Date& operator-=(int day);
	
	// 前置++
	Date& operator++();
	// 后置++
	Date operator++(int);
	// 后置--
	Date operator--(int);
	// 前置--
	Date& operator--();

	// =========== 比较运算符的重载 ==========
	// >运算符重载
	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成员函数修饰的是成员函数隐含的this指针,表明不能修改任何成员变量
	void Print() const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	// 友元声明,可以在类的任何位置
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);
private:
	int _year;
	int _month;
	int _day;
};

// 类外声明
ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);

2. 预备工作

在构造日期类时我们很有可能不小心传入错误的日期时间,比如 2023-02-29 或 2024-4-31这样的时间,所以为了确保日期的正确性,在构造函数中我们需要检查日期的合法性,因此在写构造函数前需要先实现两个成员函数:

  1. CheckInvalid() 函数:功能是检查日期是否合法
  2. GetMonthDay(int year, int month) 函数:功能是获取某年某月的天数
// 获取某年某月的天数
int Date::GetMonthDay(int year, int month) const
{
	static int days[13] = { 0,31,28,31,30,31,30,31,30,31,31,30,31 };

	if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	{
		return 29;
	}

	return days[month];
}

// 检查日期是否合法
bool Date::CheckInvalid()
{
	if (_year <= 0
		|| _month < 1 || _month > 12
		|| _day < 1 || _day > GetMonthDay(_year, _month))
	{
		return false;
	}
	return true;
}

注意:这里 days 数组被声明为静态数组,静态数组在程序的生命周期内只会被初始化一次。由于 GetMonthDay 函数被频繁调用,将其声明为静态可以确保它只在程序开始时分配一次内存,而不是每次调用函数时都重新分配。这可以提高空间效率

3. Date 类中六大默认成员函数的使用

3.1 全缺省的构造函数
// 全缺省的构造函数
Date(int year = 1900, int month = 1, int day = 1)
{
	_year = year;
	_month = month;
	_day = day;

	if (!CheckInvalid())
	{
		cout << *this << "构造日期非法" << endl;
		exit(-1);
	}
}

通过构造函数即可对实例化对象进行初始化。

3.2 拷贝构造函数

拷贝构造:同类型的一个已经存在的对象去初始化一个新的要创建的对象

// 拷贝构造函数
// d2(d1)
Date(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}
3.3 析构函数
// 析构函数
~Date()
{
	//cout << "~Date()" << endl;
}

日期类并 没有申请资源(动态开辟内存,打开文件等),所以这里的析构函数可写可不写,系统默认生成的就够用。

3.4 赋值运算符重载

赋值重载:已经存在的两个对象,一个拷贝赋值给另一个

// 赋值运算符重载
// d2 = d3 -> d2.operator=(&d2, d3)
Date& operator=(const Date& d)
{
	if (this != &d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	return *this;
}
3.5 const 成员函数
// 举例:
// 打印,const成员函数修饰的是成员函数隐含的this指针,表明不能修改任何成员变量
void Print() const
{
	cout << _year << "-" << _month << "-" << _day << endl;
}

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中 不能对类的任何成员进行修改

如果我们只需要访问成员变量而非修改成员变量,那么此时我们就可以使用 const成员函数 来提高代码的健壮性。

3.6 取地址操作符重载和const取地址操作符重载
// 取地址操作符重载
Date* operator&()
{
	return this;
	//return nullptr;
}

// const取地址操作符重载
const Date* operator&()const
{
	return this;
	//return nullptr;
}

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容

这里以注释的两个return语句为例,可以返回空指针给别人,让对方找不到指定的类对象。(所以大多数情况下我们都不需要重载这两个成员函数,使用编译器默认生成的即可


4. 运算符重载

此处详细讲解 += 和 + 运算符的重载,-= 和 - 运算符的重载与其类似。

因此,对于前置++和后置++,前置- -和后置- -运算符重载,详细讲解前者

4.1 += 和 + 运算符重载

:实现了 += 运算符的重载后,对于 + 运算符的重载就可以利用 += 运算符来实现。

// 日期+=天数
Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		if (_month == 12)
		{
			_month = 1;
			_year++;
		}
		else
		{
			_month++;
		}
	}
	return *this;
}
// 日期+天数
Date Date::operator+(int day)
{
	Date temp = *this; // 调用拷贝构造,因为temp不是一个已存在的对象

	temp += day;
	return temp;
}
  • operator+= 的算法思想和步骤:

    1. 输入Date对象的一个引用和一个整数(代表天数)。
    2. 算法思想:将给定的天数加到当前日期的天数上,并相应地调整月份和年份,以确保日期仍然有效。
    3. 步骤
      • 将当前日期的天数(_day)与给定的天数相加。
      • 检查更新后的天数是否超过了当前月份的天数(通过调用GetMonthDay函数)。
      • 如果超过了,从当前月份的天数中减去超出的部分,并更新月份和年份。
        • 如果月份是12月,将月份设置为1月,年份加1。
        • 否则,将月份加1。
      • 返回Date对象的引用,以便进行链式操作。
  • operator+ 的算法思想和步骤:

    1. 输入Date对象的一个实例和一个整数(代表天数)。
    2. 算法思想:创建一个Date对象的副本,并将给定的天数加到副本上,然后返回调整后的日期副本。
    3. 步骤
      • 创建一个Date类型的临时对象temp,并通过拷贝构造函数将其初始化为当前Date对象的副本。
      • 使用operator+=函数将给定的天数加到temp对象上。
      • 返回调整后的temp对象(值拷贝返回)。

:返回Date对象的引用(在operator+=中)允许进行链式操作,如 dateObj += 5 += 3

4.2 -= 和 - 运算符重载
// 日期-天数
Date Date::operator-(int day)
{
	Date temp = *this;

	temp -= day;
	return temp;
}
// 日期-=天数
Date& Date::operator-=(int day)
{
	while (day >= _day)
	{
		day -= _day;
		if (_month == 1)
		{
			_month = 12;
			_year--;
			_day = GetMonthDay(_year, _month);
		}
		else
		{
			_month--;
			_day = GetMonthDay(_year, _month);
		}
	}
	_day -= day;
	return *this;
}
4.3 前置++ 和 后置++ 运算符重载
  1. 前置++:返回+1之后的结果

    • 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
  2. 后置++:前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确的重载,C++规定:后置++重载时多增加一个 int 类型的参数,但调用函数时该参数不用传递,编译器自动传递

    • 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将 this 保存一份,然后给 this + 1,而temp是临时对象,因此只能以值的方式返回,不能返回引用。
// 前置++
Date& Date::operator++()
{
	*this += 1;
	return *this;
}
// 后置++
Date Date::operator++(int)
{
	Date temp = *this;
	*this += 1;
	return temp;
}
4.4 前置-- 和 后置-- 运算符重载
// 后置--
Date Date::operator--(int)
{
	Date temp = *this;
	*this -= 1;

	return temp;
}
// 前置--
Date& Date::operator--()
{
	*this -= 1;
	return *this;
}
4.5 > 和 == 运算符重载

注意:对于比较运算的重载,只要先重载了 > 和 == 运算符,其他运算符的重载就可以利用这两者来实现。

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

// ==运算符重载
bool Date::operator==(const Date& d) const
{
	return _year == d._year
		&& _month == d._month
		&& _day == d._day;
}
4.6 >= 、< 、<= 和 != 运算符重载
// >=运算符重载
bool Date::operator >= (const Date& d) const
{
	return *this > d || *this == d;
}
// <运算符重载
bool Date::operator < (const Date& d) const
{
	return !(*this >= d);
}
// <=运算符重载
bool Date::operator <= (const Date& d) const
{
	return !(*this > d);
}
// !=运算符重载
bool Date::operator != (const Date& d) const
{
	return !(*this == d);
}
4.7 日期-日期
// 日期-日期 返回天数
int Date::operator-(const Date& d)
{
	int flag = 1;
	Date maxDate = *this;
	Date minDate = d;

	if (*this < d)
	{
		flag = -1;
		maxDate = d;
		minDate = *this;
	}

	int n = 0;
	while (maxDate != minDate)
	{
		minDate++;
		n++;
	}
	return flag * n;
}
  • 思路

    1. 比较日期:首先比较当前对象(*this)和传入的日期对象d,确定哪个日期更大,哪个更小。
    2. 确定符号:根据日期的大小关系确定结果的符号。如果当前对象更大,则结果为正;如果传入的日期更大,则结果为负。
    3. 计算天数差从较小的日期开始,逐步增加一天,直到两个日期相等。每次增加一天,就增加计数器的值
    4. 返回结果:根据符号和天数差计算最终的结果,并返回。
  • 步骤

    1. 声明变量
      • flag:用于表示结果的符号,初始化为1(表示正数)。
      • maxDateminDate:用于存储两个日期中较大和较小的日期,初始时分别设置为当前对象(*this)和传入的日期d
    2. 比较日期并确定符号
      • 使用if语句比较*thisd
      • 如果*this小于d,则交换maxDateminDate的值,并将flag设置为-1。
    3. 初始化计数器
      • 声明n并初始化为0,用于计算天数差。
    4. 计算天数差
      • 使用while循环,每次循环将minDate增加一天(即调用minDate++),并增加计数器n的值。
      • 循环继续直到maxDateminDate相等。
    5. 返回结果
      • flagn相乘,得到最终的结果,并返回。
4.8 流插入 << 和 流提取 >> 运算符重载

有了日期类那么我们需要打印日期信息该怎么办呢?

  1. 我们可以实现一个 Print 成员函数来实现:
// 打印,const成员函数修饰的是成员函数隐含的this指针,表明不能修改任何成员变量
void Print() const
{
	cout << _year << "-" << _month << "-" << _day;
}

在这里插入图片描述

但是每次都要调用函数来打印日期是不是太麻烦了,有没有更简单的方法,就像内置类型(int、char等)那样直接使用 cout 打印呢?

  1. 在C++中,对于自定义类型可以重载流插入 << 来实现像内置类型一样的输出操作

在这里插入图片描述
cout 是一个 ostream 类型的对象。

// 流插入<< 重载
ostream& operator<<(ostream& out, const Date& d)
{
	// 输出格式化字符串到输出流  
	out << d._year << "-" << d._month << "-" << d._day << endl;
	// 返回输出流引用以支持链式操作
	return out;
}

在这里插入图片描述

【思路】:

  1. 定义重载函数:定义一个函数,接受一个ostream引用和一个const Date&引用作为参数。
  2. 输出格式化字符串:在函数内部,使用输出流out来格式化并输出Date对象的年、月、日信息。
  3. 返回输出流引用:为了支持链式输出,函数应返回ostream引用

注意事项:

  • 在使用流插入 << 时,要确保第一个参数是ostream的对象,如果是在重载的时候写成成员函数,编译器就会将第一个参数默认传入this指针,因此只能将其重载成全局函数,传入两个参数,第一个为ostream的对象,第二个为Date类对象。
  • 相应的,重载成了全局函数必然会导致类中的私有成员不能被访问,那么这又该如何呢?这里有两种解决办法:
    1. 创建公有的成员函数getYeargetMonthgetDay,这样就可以通过这些函数去访问私有成员变量,java很喜欢使用这种方式。
    2. 使用友元函数,当一个函数或类被声明为另一个类的友元时,它可以访问该类的所有成员,包括私有成员
      在这里插入图片描述

既然有流插入 >> 运算符的重载,那么必然就有流提取 >> 运算符的重载。

  1. 在C++中,对于自定义类型可以重载流提取 >> 来实现像内置类型一样的输入操作

在这里插入图片描述
cin 是一个 istream 类型的对象。

// 流提取 >> 重载
istream& operator>>(istream& in, Date& d)
{
	while (1)
	{
		cout << "请依次输入年 月 日:>";
		in >> d._year >> d._month >> d._day;

		if (!d.CheckInvalid())
		{
			cout << "亲,你输入了无效日期,请重新输入!" << endl;
		}
		else
		{
			break;
		}
	}
	// 返回输入流引用以支持链式操作
	return in;
}

在这里插入图片描述

【思路】

  1. 定义重载函数:定义一个函数,接受一个istream引用和一个Date&引用作为参数。
  2. 输入日期:从输入流中读取年、月、日,并尝试赋值给Date对象。
  3. 验证日期:调用Date对象的CheckInvalid方法来检查输入的日期是否有效。
  4. 错误处理:如果日期无效,则输出错误消息并继续循环,要求用户重新输入。
  5. 返回输入流引用:如果日期有效,则退出循环并返回输入流的引用,以支持链式输入。

5. 日期类源码

5.1 Date.h文件

#pragma once

#include <iostream>

using namespace std;

class Date
{
public:
	// 获取某年某月的天数
	int GetMonthDay(int year, int month) const;
	// 检查日期是否合法
	bool CheckInvalid();

	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;

		if (!CheckInvalid())
		{
			cout << *this << "构造日期非法" << endl;
			exit(-1);
		}
	}

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

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

	// 析构函数
	~Date()
	{
		//cout << "~Date()" << endl;
	}

	// 取地址操作符重载
	Date* operator&()
	{
		return this;
		//return nullptr;
	}

	// const取地址操作符重载
	const Date* operator&()const
	{
		return this;
		//return nullptr;
	}

	// 日期+=天数
	Date& operator+=(int day);
	// 日期+天数
	Date operator+(int day);
	// 日期-天数
	Date operator-(int day);
	// 日期-=天数

	Date& operator-=(int day);
	// 前置++
	Date& operator++();
	// 后置++
	Date operator++(int);
	// 后置--
	Date operator--(int);
	// 前置--
	Date& operator--();

	// >运算符重载
	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成员函数修饰的是成员函数隐含的this指针,表明不能修改任何成员变量
	void Print() const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	// 友元声明,可以在类的任何位置
	friend ostream& operator<<(ostream& out, const Date& d);
	friend istream& operator>>(istream& in, Date& d);
private:
	int _year;
	int _month;
	int _day;
};

// 类外声明
ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);

5.2 Date.cpp 文件

#define _CRT_SECURE_NO_WARNINGS 1

#include "Date.h"

// 获取某年某月的天数
int Date::GetMonthDay(int year, int month) const
{
	static int days[13] = { 0,31,28,31,30,31,30,31,30,31,31,30,31 };

	if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
	{
		return 29;
	}

	return days[month];
}

// 日期+=天数
Date& Date::operator+=(int day)
{
	_day += day;
	while (_day > GetMonthDay(_year, _month))
	{
		_day -= GetMonthDay(_year, _month);
		if (_month == 12)
		{
			_month = 1;
			_year++;
		}
		else
		{
			_month++;
		}
	}
	return *this;
}
// 日期+天数
Date Date::operator+(int day)
{
	Date temp = *this; // 调用拷贝构造,因为temp不是一个已存在的对象

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

	temp -= day;
	return temp;
}
// 日期-=天数
Date& Date::operator-=(int day)
{
	while (day >= _day)
	{
		day -= _day;
		if (_month == 1)
		{
			_month = 12;
			_year--;
			_day = GetMonthDay(_year, _month);
		}
		else
		{
			_month--;
			_day = GetMonthDay(_year, _month);
		}
	}
	_day -= day;
	return *this;
}

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

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

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

// 日期-日期 返回天数
int Date::operator-(const Date& d)
{
	int flag = 1;
	Date maxDate = *this;
	Date minDate = d;

	if (*this < d)
	{
		flag = -1;
		maxDate = d;
		minDate = *this;
	}

	int n = 0;
	while (maxDate != minDate)
	{
		minDate++;
		n++;
	}
	return flag * n;
}

// 检查日期是否合法
bool Date::CheckInvalid()
{
	if (_year <= 0
		|| _month < 1 || _month > 12
		|| _day < 1 || _day > GetMonthDay(_year, _month))
	{
		return false;
	}
	return true;
}

// 流插入 << 重载
ostream& operator<<(ostream& out, const Date& d)
{
	// 输出格式化字符串到输出流  
	out << d._year << "-" << d._month << "-" << d._day << endl;
	// 返回输出流引用以支持链式操作
	return out;
}
// 流提取 >> 重载
istream& operator>>(istream& in, Date& d)
{
	while (1)
	{
		cout << "请依次输入年 月 日:>";
		in >> d._year >> d._month >> d._day;

		if (!d.CheckInvalid())
		{
			cout << "亲,你输入了无效日期,请重新输入!" << endl;
		}
		else
		{
			break;
		}
	}
	// 返回输入流引用以支持链式操作
	return in;
}

总结

🔥💖 此日期类是一个非常适合大家训练自己对运算符重载知识理解和掌握的小项目,它是C++引用传值/传引用返回拷贝构造赋值重载运算符重载const成员函数const修饰参数等知识的一个融合,相信大家在上手练习的过程中能收获颇丰。

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

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

相关文章

海外媒体发稿:提升国外影响力的7种汽车媒体推广方法-华媒舍

伴随着全球化发展的推动&#xff0c;汽车市场已经变成世界各地关注的重点领域之一。提升汽车知名品牌在海外的影响力对于企业的发展趋势尤为重要。下面我们就详细介绍7种提升国外影响力的汽车媒体推广方法&#xff0c;协助汽车公司能够更好地进到国外市场。 1.公布知名品牌新闻…

Vue中有哪些优化性能的方法?

Vue是一款流行的JavaScript框架&#xff0c;用于构建交互性强的Web应用程序。在前端开发中&#xff0c;性能优化是一个至关重要的方面&#xff0c;尤其是当应用程序规模变大时。Vue提供了许多优化性能的方法&#xff0c;可以帮助开发人员提升应用程序的性能&#xff0c;从而提升…

【ESP32 IDF】I2C层次结构、I2C协议

文章目录 前言一、I2C的结构层次1.1 怎样在两个设备之间传输数据1.2 I2C如何传输数据1.3 硬件框图1.4 软件层次 二、IIC协议2.1 硬件连接2.2 I2C 总线的概念2.3 传输数据类比2.3 I2C信号2.4 I2C数据的含义 总结 前言 I2C&#xff08;Inter-Integrated Circuit&#xff09;是一…

第 5 章 ROS常用组件静态坐标变换(自学二刷笔记)

5.1.2 静态坐标变换 所谓静态坐标变换&#xff0c;是指两个坐标系之间的相对位置是固定的。 需求描述: 现有一机器人模型&#xff0c;核心构成包含主体与雷达&#xff0c;各对应一坐标系&#xff0c;坐标系的原点分别位于主体与雷达的物理中心&#xff0c;已知雷达原点相对于…

【好书推荐-第九期】Sora核心技术相关书籍《扩散模型:从原理到实战》与《GPT 图解:大模型是怎样构建的》:Sora的两大核心技术,都藏在这两本书里!

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主、前后端开发、人工智能研究生。公众号&#xff1a;洲与AI。 &#x1f388; 本文专栏&#xff1a;本文收录…

《Vite 报错》ReferenceError: module is not defined in ES module scope

ReferenceError: module is not defined in ES module scope 解决方案 postcss.config.js 要改为 postcss.config.cjs&#xff0c;也就是 .cjs 后缀。 原因解析 下图提示&#xff0c;packages.json 中的属性 type 设置为 module。所有 *.js 文件现在都被解释为 ESM&#xff…

【vue/组件封装】封装一个带条件筛选的搜索框组件(多组条件思路、可多选)详细流程

引入&#xff1a;实现一个带有筛选功能的搜索框&#xff0c;封装成组件&#xff1b; 搜索框长这样子&#xff1a; 点击右侧筛选图标后弹出层&#xff0c;长这样子&#xff1a; 实际应用中有多组筛选条件&#xff0c;这里为了举栗子就展示一组&#xff1b; 预览&#xff1a;…

Windows环境中Domain Controller (域控制器)的搭建,零基础教学详细教程

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;网络安全渗透 景天的主页&#xff1a;景天科技苑 文章目录 1.搭建域环境2.搭建过程2.1.安装域控2.2.建立域的普通用户2.3.把…

BUUCTF:[MRCTF2020]ezmisc

题目地址&#xff1a;https://buuoj.cn/challenges#[MRCTF2020]ezmisc 下载附件打开是一张照片&#xff1a; 放到kali中发现crc校验错误&#xff0c;修改照片宽高&#xff1a; 保存即可发现flag flag为&#xff1a; flag{1ts_vEryyyyyy_ez!}

为什么MySQL中多表联查效率低,连接查询实现的原理是什么?

MySQL中多表联查效率低的原因主要涉及到以下几个方面&#xff1a; 数据量大: 当多个表通过连接查询时&#xff0c;如果这些表的数据量很大&#xff0c;那么查询就需要处理更多的数据&#xff0c;这自然会降低查询效率。 连接操作复杂性: 连接查询需要对参与连接的每个表中的数…

HTTPS是什么,那些行业适合部署呢?

随着在线活动的增加&#xff0c;对您共享的关键数据的威胁已经产生了严重的后果&#xff0c;包括欺诈性金融交易、在线身份盗窃等。此外&#xff0c;随着技术使用的增加&#xff0c;网络攻击也变得更加复杂和具有挑战性。 毫无疑问&#xff0c;互联网用户的数据安全意识成倍增长…

QVector和QString互相转换

我的画图项目需要读写自定义虚线样式 {...comboBox_penStyle new QComboBox;QStringList SL_penStyle;SL_penStyle << "______" << "----------" << ".........." << "-.-.-.-.-." << "-..-..-..…

openEuler 社区 2024 年 2 月运作报告

概述 2024年2月中旬&#xff0c;OpenAtom openEuler&#xff08;简称"openEuler"&#xff09;2023 社区年报发布。这是社区开源四年来&#xff0c;在生态构建、技术创新、产业聚集、人才培养等方面发展的成果展示&#xff0c;也是社区1400多家成员单位、1.7万多名开…

前面说什么是前后端分类,那到底是怎么个分类法呢?

前后端分离是指将一个web 系统的动态内容和静态内容进行分离&#xff0c;包括其开发、部署等。 比如传统的 MVC 架构&#xff0c;HTML、JS、CSS… 等前端代码和 Java、spring、mybatis… 等后端代码是在同一个项目中进行开发、部署的。那前后端分离后&#xff0c;就可以分多个项…

深入浅出解析SSL:保障网络安全的加密技术

在数字信息时代&#xff0c;网络安全已成为人们关注的重点。为了在网络传输过程中保护数据的完整性和机密性&#xff0c;我们需要一种强大的安全协议——SSL&#xff08;安全套接层&#xff09;。今天德迅云安全就带大家来简单了解下SSL是什么&#xff0c;它的工作原理以及为何…

Java中常见延时队列的实现方案总结

&#x1f3f7;️个人主页&#xff1a;牵着猫散步的鼠鼠 &#x1f3f7;️系列专栏&#xff1a;Java全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&…

Intel RealSense D435环境搭建之安装pyrealsense2

ERROR: Could not find a version that satisfies the requirement pyrealsense2 (from versions: none) pip install pyrealsense2 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com 方法一&#xff1a;升级pip python -m pip install --upgrade pip 方…

Redis第6讲——主从复制模式详解

Redis的读写性能很高&#xff0c;但在面对大规模数据和高发访问的挑战时&#xff0c;单节点的Redis可能无法满足需求&#xff0c;这就引出了Redis集群的概念。本节先介绍一下Redis高可用方案之一的主从复制模式&#xff0c;虽说现在基本不会用这种模式&#xff0c;但是无论是哨…

【VTKExamples::PolyData】第四十九期 Silhouette

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ:870202403 前言 本文分享VTK样例Silhouette,并解析接口vtkPolyDataSilhouette,希望对各位小伙伴有所帮助! 感谢各位小伙伴的点赞+关注,小易会继续努力分享,一起进步! 你的点赞就是我的动力(^U^)ノ~YO 1. Silhouett…

C语言数组全面解析:从初学到精通

数组 1. 前言2. 一维数组的创建和初始化3. 一维数组的使用4. 一维数组在内存中的存储5. 二维数组的创建和初始化6. 二维数组的使用7. 二维数组在内存中的存储8. 数组越界9. 数组作为函数参数10. 综合练习10.1 用函数初始化&#xff0c;逆置&#xff0c;打印整型数组10.2 交换两…