C++类与对象(中)

news2024/11/28 22:46:42

✅<1>主页:我的代码爱吃辣
📃<2>知识讲解:C++
🔥<3>创作者:我的代码爱吃辣
☂️<4>开发环境:Visual Studio 2022
💬<5>前言:C++类中一共有六个默认成员函数,今天我们先来将剩下的赋值重载,和取地址重载,以及实现Date类。

目录

一.运算符重载

二.赋值运算符重载格式:

三.前置++和后置++重载

四.const成员

五.取地址及const取地址操作符重载 

六. cout 输出类信息

七.Date类实现

(1)Date类的主要功能模块

(2)日期大小比较

(3)日期+天数,日期+=天数,++日期,日期++

(4)日期-日期,日期-天数,日期-=天数

测试


一.运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其
返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:关键字operator后面接需要重载的运算符符号。 

函数原型:返回值类型 operator操作符(参数列表)。

假如我们需要实现一个日期加上一个天数得到一个新的日期,此时按照我们以前的思考方式,是实现一个函数,但是利用运算符重载,会变得更加直观明了

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void show()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	
	int _year;
	int _month;
	int _day;
};
//函数判断日期相等
bool DateEqual(const Date& d1, const Date& d2)
{
	return d1._year == d2._year &&
		d1._month == d2._month &&
		d1._day == d2._day;
}
//运算符重载的定义 使用关键字 operator 【运算符】
bool operator==(const Date& d1 ,const Date& d2)
{
	return d1._year == d2._year &&
		   d1._month == d2._month && 
		   d1._day == d2._day;
}
int main()
{
	Date d2(2022, 4, 23);
	Date d1(2022, 1, 13);
	//函数使用
	if (DateEqual(d1, d2))
		cout << "true" << endl;
	else
		cout << "false" << endl;

	//运算符重载的使用
	if (d1 == d2)
		cout << "true" << endl;
	else
		cout << "false" << endl;
	
	return 0;
}

但是一般我们的成员变量都是私有的,如果是私有的我们就不能直接访问,我们通过添加 get函数来解决,或者通过将运算符重载的函数写道类的里面,变成成员函数,这里我们就直接封装到类里面:

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}

    // bool operator==(Date* this, const Date& date)
    // 这里需要注意的是,左操作数是this,指向调用函数的对象
	bool operator ==(const Date& date)
	{
		return _year == date._year &&
               _month == date._month && 
               _day == date._day;
	}
            
	void show()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
	
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d2(2022, 1, 13);
	Date d1(2022, 1, 13);
	//运算符重载的使用
	if (d1 == d2)
		cout << "true" << endl;
	else
		cout << "false" << endl;
	
	return 0;
}

注意:在将运算符重载写成成员成员函数时,重载运算符只需要写一个参数即可,因为有一个参数就是本对象本身,就是隐藏在成员函数列表的this指针。

二.赋值运算符重载格式:

1.参数类型:const T&,传递引用可以提高传参效率

2.返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值检测是否自己给自己赋值

3.返回*this :要复合连续赋值的含义

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 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)
	{
        //如果不是自身赋值,即d1=d1,才需要成员变量对用赋值。
		if (this != &d)
		{
			_year = d._year;
			_month = d._month;
			_day = d._day;
		}
		return *this;
	}
	void show()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date date1;
	Date date2(2023, 2, 7);
	date1.show();
	//因为有返回值就可以实现链式访问
	(date1 = date2).show();
	return 0;
}

 4. 赋值运算符只能重载成类的成员函数不能重载成全局函数

class Date{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	int _year;
	int _month;
	int _day;
};
//赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{
	if (&left != &right)
	{
		left._year = right._year;
		left._month = right._month;
		left._day = right._day;
	}
	return left;
}

 原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现
一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值
运算符重载只能是类的成员函数。

5.用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。

class Time
{
public:
	Time()
	{
		_hour = 1;
		_minute = 1;
		_second = 1;
	}
	Time& operator=(const Time& t)
	{
		if (this != &t)
		{
			cout << "Time:operator=" << endl;
			_hour = t._hour;
			_minute = t._minute;
			_second = t._second;
		}
		return *this;
	}
	
private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void show()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	// 基本类型(内置类型)
	int _year ;
	int _month;
	int _day;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d1;
	d1.show();
	Date d2(2023,2,7);
	d1 = d2;
	d1.show();
	return 0;
}

注意:内置类型成员变量是直接赋值的,而自定义类型成员变.量需要调用对应类的赋值运算符
重载完成赋。

但是对于有空间申请的空间是需要,我们不能光靠编译器自己生成的赋值运算符重载的:

class A
{
public:
	A()
	{
		a = 10;
		arr = (int*)malloc(sizeof(int) * a);
		for (int i = 0; i < a; i++)
		{
			arr[i] = i;
		}
	}
	void show()
	{
		for (int i = 0; i < a; i++)
		{
			cout << arr[i] << " ";
		}
		cout << endl;
	}

	int* arr;
	int a;
};
int main()
{
	A a;
	A b;
	a.show();
	b.show();
	b = a;
	//修改b对象的arr数组
	for (int i = 0; i < b.a; i++)
	{
		b.arr[i] = 0;
	}
	//观察两个对象中arr的元素
	b.show();
	a.show();
	return 0;
}

 我们只是修改了b对象的 arr 数组,但是a对象的arr数组也被跟着修改了。

具体的情况是:

三.前置++和后置++重载

我们知道前置++和后置++唯一的区别就是,返回值不同。前置++返回++之后的结果,前置++返回++之后的结果。那么运算符重载以后也应该支持前置++和后置++的特性。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	// 前置++:返回+1之后的结果
	// 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率
	Date& operator++()
	{
		_day += 1;
		return *this;
	}
	// 后置++:
	// 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载
	// C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递
	// 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给this + 1
	// 而temp是临时对象,因此只能以值的方式返回,不能返回引用
	Date operator++(int)
	{
		Date temp(*this);
		_day += 1;
		return temp;
	}
	void show()
	{
		cout << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1(2022, 10, 1);
	d1.show();
	Date d2 = d1++;
	d2.show();
	d1.show();

	d2 = ++d1;
	d1.show();
	d2.show();

	return 0;
}

四.const成员

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

class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void Print()
	{
		cout << "Print()" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl << endl;
	}
	void ConstPrint() const
	{
		cout << "Print()const" << endl;
		cout << "year:" << _year << endl;
		cout << "month:" << _month << endl;
		cout << "day:" << _day << endl << endl;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};
int main()
{
	Date d1(2022, 1, 13);
	d1.Print();
	const Date d2(2022, 1, 13);
	d2.ConstPrint();
	return 0;
}

 思考下面的几个问题:
1. const对象可以调用非const成员函数吗?

解答:const对象不可以调用非const成员函数,因为非const成员函数的*this也是没有经过const修饰的,如果调用了const成员函数,就相当于权限放大。
2. 非const对象可以调用const成员函数吗?

解答:非const对象可以调用const成员函数,因为由const修饰的成员函数实际上修饰的就是*this,相当于权限缩小,是允许的。
3. const成员函数内可以调用其它的非const成员函数吗?

解答:const成员函数不可以调用其他的非const成员函数,也是一个权限放大的例子。
4. 非const成员函数内可以调用其它的const成员函数吗?

解答:非const成员函数可以调用其他的const成员函数,也是一个权限缩小的例子。

五.取地址及const取地址操作符重载 

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。

class Date
{
public:
	Date* operator&()
	{
		return this;
	}
	const Date* operator&()const
	{
		return this;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};
int main()
{
	Date date;
	cout << &date << endl;
	return 0;
}

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


class Date
{
public:
	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	Date* operator&()
	{
		return (Date*)0x00000001;
	}
	const Date* operator&()const
	{
		return (Date*)0x0000250;
	}
private:
	int _year; // 年
	int _month; // 月
	int _day; // 日
};

int main()
{
	const Date date(2022,10,1);
	Date date1(date);
	cout << &date << endl;
	cout << &date1 << endl;

	return 0;
}

六. cout 输出类信息

cout是类 ostream 的对象,表示面向窄字符(字符类型)的标准输出流。它对应于 C 流标准输出

作为 ostream 类的对象,可以使用插入运算符(运算符<<)将字符作为格式化数据写入其中,也可以使用成员函数(如 write)将字符作为无格式数据写入其中。

 对象在带有外部链接和静态持续时间的头文件声明<iostream>:它持续整个程序的持续时间。

 我们可以将ostream的对象cout,也作为运算符重载的参数:

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//<<运算符重载
	void operator<<(ostream& out)
	{
		out << _year << "/" << _month << "/" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date date(2023, 2, 8);
	//按照运算符左边到右边是参数从左往右对应
	//成员函数第一个参数就是this指针,所以<<运算符左边就是date对象
	date << cout;
	//等价于
	date.operator<<(cout);
	return 0;
}

 但是 date<<cout ,非常不符合我们的使用习惯,有没有一种办法可以实现 cout << date 呢?造成这种情况的原因是成员函数的第一个参数默认是 this 指针,如果我们不将 << 设计为成员函数是不是就可以解决这个问题呢?

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};
//<<运算符重载
void operator<<(ostream& out, Date& d)
{
	out << d._year << "/" << d._month << "/" << d._day << endl;
}
int main()
{
	Date date(2023, 2, 8);
	//按照运算符左右参数,分别对应<<运算符重载从左往右的参数
	cout << date;
	//等价于
	operator<<(cout, date);
	return 0;
}

 

 这就又有一个新的问题,成员变量私有化,不允许外部函数直接访问,面对这个问题,我们有两种解决方案:

1.设置get函数

设计成员函数用于返回私有成员变量的值,供外部读取。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//Get函数,用于外部读取私有成员变量
	int& Get_year()
	{
		return _year;
	}
	int& Get_month()
	{
		return _month;
	}
	int& Get_day()
	{
		return _day;
	}
private:
	int _year;
	int _month;
	int _day;
};
//<<运算符重载,为了支持连续访问,加上返回值
otsream& operator<<(ostream& out, Date& d)
{
	out << d.Get_year() << "/" << d.Get_month() << "/" << d.Get_day() << endl;
    return out;
}
int main()
{
	Date date(2023, 2, 8);
	//按照运算符左右参数,分别对应<<运算符重载从左往右的参数
	cout << date;
	//等价于
	operator<<(cout, date);
	return 0;
}

 2.设计友元函数

只需在将函数声明写在Date类的内部,并在函数的前面加上关键字 friend,就可以和类建立友好关系,友元函数可以像成员函数一样随意访问成员变量。

class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	//友元函数
	friend void operator<<(ostream& out, Date& d);
private:
	int _year;
	int _month;
	int _day;
};
//<<运算符重载
void operator<<(ostream& out, Date& d)
{
	out << d._year << "/" << d._month << "/" << d._day << endl;
}
int main()
{
	Date date(2023, 2, 8);
	//按照运算符左右参数,分别对应<<运算符重载从左往右的参数
	cout << date;
	//等价于
	operator<<(cout, date);
	return 0;
}

七.Date类实现

前面一直在用Date类举例子,这次我们来全面实现一下,练习我们之前学过的类与对象的姿势。

我们严格按照开发标准来实现Date类:

(1)Date类的主要功能模块

//Date.h文件
#include<iostream>
#include<assert.h>
using namespace std;
class Date
{
	friend ostream& operator<<(ostream& out, Date& d);
public:
	Date(int year, int month, int day );
	//日期比较大小
	bool operator>(const Date& date);
	bool operator >= (const Date& date);
	bool operator <(const Date& date);
	bool operator<=(const Date& date);
	bool operator ==(const Date& date);
	//日期+天数
	Date operator+(int x);
	//日期+=天数
	Date& operator+=(int x);

	//日期-日期=天数
	int operator-(const Date& date);
	//日期-天数=日期
	Date operator-(int x);
	//日期-=天数
	Date operator-=(int x);

	//Date++
	Date operator++(int);
	//++Date
	Date& operator++();
private:
	int GetMonthDay(int year, int month);//获取每月天数
	int _year;//年
	int _month;//月
	int _day;//日
};

//Date.cpp
//构造函数定义
Date::Date(int year , int month, int day)
{
	assert(month <= 12 && day <= this->GetMonthDay(year, month));
	_year = year;
	_month = month;
	_day = day;
}
//输出日期:年/月/日(友元函数)
void operator<<(ostream& out, Date& d)
{
	out << d._year << "/" << d._month << "/" << d._day << endl;
}

(2)日期大小比较

//Date.cpp
bool Date::operator>(const Date& date)
{
	if (_year != date._year)//如果年不相等,直接判断出结果
		return _year > date._year;
	if (_month != date._month)//年相等的时候,如果月不相等,直接判断出结果
		return _month > date._month;
	if (_day != date._day)//年.月相等的时候,如果日不相等,直接判断出结果
		return _day > date._day;
}

bool Date::operator >= (const Date& date)
{
    //>=就是或上一个相等
	return *this > date || *this == date;
}

bool Date::operator ==(const Date& date)
{    
    //相等需要年月日都相等
	return _year == date._year && _month == date._month && _day == date._day;
}

bool Date::operator <(const Date& date)
{    
    // >=取反
	return !(*this >= date);
}

bool Date::operator<=(const Date& date)
{    
    //<或上==
	return *this < date || *this == date;
}

(3)日期+天数,日期+=天数,++日期,日期++

int Date::GetMonthDay(int year, int month)
{
	int montharr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	if (((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)&&month==2)
	{
		return 29;
	}
	return montharr[month];
}

Date Date::operator+(int x)
{
	
	Date tmp(*this);
	if (x < 0)
	{
		tmp -= -x;
		return tmp;
	}
	tmp += x;
	return tmp;
}
//先将天数全部加上去,然后依次减去当月天数,并判断年月的变换。
Date& Date::operator+=(int x)
{
	if (x < 0)
	{
		*this -= -x;
		return *this;
	}
	_day += x;
	while (_day > GetMonthDay(_year,_month))
	{
		_day -= this->GetMonthDay(_year,_month);
		_month++;
		if (_month > 12)
		{
			_year++;
			_month = 1;
		}
	}
	return *this;
}


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

(4)日期-日期,日期-天数,日期-=天数

//计数计算,一天一天加,直到日期相等。
int Date::operator-(const Date& date)
{
	int count = 0;

	Date bigdate = *this;
	Date smalldate = date;
	if (bigdate < smalldate)
	{
		Date tmp = bigdate;
		bigdate = smalldate;
		smalldate = tmp;
	}
	
	while (!(smalldate == bigdate))
	{
		smalldate++;
		count++;
	}
	return count;
}

//日期-天数,先算整数月的减法,直到剩下的天数,小于本月天数,
//加上第一个月,和最后一个月的剩下的天数计算
Date Date::operator-(int x)
{
	Date tmp(*this);
	if (x < 0)//如果天数小于0,就相当于加上天数
	{
		tmp += -x;
		return tmp;
	}
	tmp._month--;
	if (tmp._month == 0)
	{
		tmp._month = 12;
		tmp._year--;
	}
	tmp._day = tmp.GetMonthDay(tmp._year, tmp._month);

	while (x > tmp.GetMonthDay(tmp._year, tmp._month))
	{
		x -= tmp.GetMonthDay(tmp._year, tmp._month);
		tmp._month--;
		if (tmp._month == 0)
		{
			tmp._month = 12;
			tmp._year--;
		}
		tmp._day = tmp.GetMonthDay(tmp._year, tmp._month);
	}
	tmp._day -= x;
	return tmp + this->_day;
}
//不仅计算返回,而且修改当前对象
Date Date::operator-=(int x)
{
	if (x < 0)
	{
		*this += -x;
		return *this;
	}
	*this = *this - x;
	return *this;
}

测试

 

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

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

相关文章

当ChatGPT遇到网络安全

ChatGPT&#xff1a;是人工智能技术驱动的自然语言处理工具&#xff0c;它能够通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人类一样来聊天交流&#xff0c;甚至能完成撰写邮件、视频脚本、文案、翻译、代码等任务。GPT 是 …

活动星投票文艺巡演活动免费投票程序制作网页投票网站

“文艺巡演活动”网络评选投票_线上小程序的投票方式_视频投票的功能_在线投票程序用户在使用微信投票的时候&#xff0c;需要功能齐全&#xff0c;又快捷方便的投票小程序。而“活动星投票”这款软件使用非常的方便&#xff0c;用户可以随时使用手机微信小程序获得线上投票服务…

ConcurrentHashMap底层原理介绍

概述: ConcurrentHashMap相对于HashMap的性能较差一些,但相比于Hashtable而言性能要高很多,因为Hashtable内部的所有方法都是同步方法,加了synchronized锁,所以性能上比较差,但在多线程环境下是具有很强的安全性的ConcurrentHashMap避免了对全局加锁改成了局部加锁操作&#xf…

Go最新版下载 Go1.20版新特性

Go官方正式发布了Go1.20稳定版 该版本依然保持 Go1 兼容性&#xff0c;可以升级到 Go1.20&#xff0c;而不需要做任何代码改动。 可以使用你任何喜欢的方式升级&#xff1a; 比如&#xff1a; go install golang.org/dl/go1.20latest 具体的可以参考官网教程&#xff1a; ht…

简介DNS协议、ICMP协议、NAT技术

文章目录一、DNS 协议1.背景2.域名二、ICMP 协议1.功能2.格式3. ping 命令4. traceroute 命令三、NAT 技术1.基本理解2. NAT 转换过程3. NAPT4. NAT 技术的缺陷5. NAT 和代理服务器一、DNS 协议 DNS&#xff08;Domain Name System&#xff0c;域名系统&#xff09;&#xff0…

【头歌】串的运算及应用

串的运算及应用第1关&#xff1a;求子串任务描述本关任务&#xff1a;实现字符串的求子串操作。相关知识为了完成本关任务&#xff0c;你需要理解&#xff1a;1. 求子串操作&#xff0c;2.字符串的顺序存储。求子串操作从一个字符串S的某个位置开始截取若干个连续字符&#xff…

采样电路的3个组成部分

采样电路的使用实际上是电路的一个闭环控制过程&#xff0c;也可以理解为一个负反馈过程&#xff0c;采集的信号被传送到主控制芯片进行调整。今天就来为您介绍一下采样电路的三个组成部分分析&#xff01;一起来看看吧&#xff01; 这里的采样实际上分为电流采样、电压采样、…

((蓝桥杯 刷题全集)【备战(蓝桥杯)算法竞赛-第6天(动态规划 专题)】( 从头开始重新做题,记录备战竞赛路上的每一道题 )距离蓝桥杯还有61天

&#x1f3c6;&#x1f3c6;&#x1f3c6;&#x1f3c6;&#x1f3c6;&#x1f3c6;&#x1f3c6; 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&a…

EMR Studio 要点梳理

文章目录1. 关系梳理2. 网络配置2.1 必须是在私有子网中的EMR集群才可以被EMR Studio连接吗&#xff1f;2.2 关于网络安全组&#xff1a;DefaultEngineSecurityGroup 和 DefaultWorkspaceSecurityGroupGit2.3 18888端口2.4 无法访问Github的解决方法3. 集成Windwos AD身份认证4…

【王道数据结构】第六章(上) | 图详解

目录 一、图的基本概念 二、图的存储 1、邻接矩阵法 2、邻接表法(顺序链式存储) 3、十字链表存储 4、邻接多重表 三、图的基本操作 四、图的遍历 1、广度优先遍历 2、深度优先遍历 一、图的基本概念 1、图的定义 2、无向图 若E是无向边 简称边) 的有限集合时&#xff…

如何使用MongoDB?

一&#xff1a;与MySQL区别 RDBMS 与 MongoDB 对应的术语&#xff1a; 类似于mysql&#xff0c;刚开始数据库、集合都是要创建之后才有的。 但是每次插入数据时都是插入一个对象&#xff0c;整个对象就是文档&#xff0c;对象的属性名就是字段。字段是不需在提前创建时声明的…

linux基本功之fsck命令详解

&#x1f493; 大家好&#xff0c;我是沐风晓月&#xff0c;双一流院校英语计算机双专业在读&#xff1b; &#x1f493; 想要学好Linux&#xff0c;命令是基本功&#xff0c;企业中常用的命令大约200多个&#xff0c;不管是写shell脚本还是管理操作系统&#xff0c;最常用的命…

理解Keil编译器中编译程序时出现的Code、RO-data、RW-data和ZI-data的含义

** 1&#xff1a;Code、RO-data、RW-data和ZI-data ** STM32单片机在keil开发环境下编译完成后&#xff0c;会显示: Program Size: Codexxxx RO-dataxxxx RW-dataxxxx ZI-dataxxxx 编译后的显示窗口如图所示&#xff1a; 其中Code、RO-data、RW-data和ZI-data是什么意思呢&…

基于OpenCV 的车牌识别

基于OpenCV 的车牌识别 车牌识别是一种图像处理技术&#xff0c;用于识别不同车辆。这项技术被广泛用于各种安全检测中。现在让我一起基于 OpenCV 编写 Python 代码来完成这一任务。 车牌识别的相关步骤 1. 车牌检测&#xff1a;第一步是从汽车上检测车牌所在位置。我们将使用…

基于matlab模拟雷达海杂波PPI

一、前言此示例演示如何在海洋环境中模拟旋转天线阵列的计划位置指示器 &#xff08;PPI&#xff09; 雷达图像。您将配置雷达方案和光谱海面模型&#xff0c;使用点散射体集合模拟扩展目标&#xff0c;生成返回信号&#xff0c;并绘制结果的 PPI 图像。二、配置雷达方案设置 R…

Word操作与应用

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.Office中Word简介 二.word工作环境 1.WPS简介 2.启动Word …

通过环境变量来绕过Windows Defender和隐藏混淆行为

什么是环境变量 关于什么是环境变量&#xff0c;我这篇文章介绍的很清楚 https://blog.csdn.net/qq_45894840/article/details/128622314?spm1001.2014.3001.5502这里在扩展一点 env env是英文单词environment的缩写&#xff0c;其功能是用于显示和定义环境变量&#xff0…

Mybatis源码(一) Mybatis是如何与spring框架整合的

Mybatis是现在最流行的数据库中间件之一&#xff0c;用mybatis的好处在于让开发者更专注在SQL本身&#xff0c;能与多种数据库兼容&#xff0c;而spring框架又是java最强大的框架&#xff0c;对于java来讲&#xff0c;万物是基于spring 的&#xff0c;因此我们有必要去理解myba…

若依框架---PageHelper分页(十三)

我们介绍了PageHelper中的cache包以及简单介绍了包中各个类的属性与方法&#xff1b;还介绍了Java中一种加载类的方式&#xff1a;Class.forName&#xff0c;并且通过查看com.mysql.jdbc.Driver代码&#xff0c;我们知道&#xff0c;可以通过这种方式可以执行类中的静态代码段。…

python进阶——自动驾驶寻找车道

大家好&#xff0c;我是csdn的博主&#xff1a;lqj_本人 这是我的个人博客主页&#xff1a; lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…