【C++第三课 - 类和对象中】构造函数、析构函数、拷贝构造函数、赋值重载、取地址重载、Date类的完善、const成员

news2024/11/20 4:56:54

目录

  • 类的6个默认成员函数
    • 构造函数
      • 自己写的构造函数
      • 默认生成的构造函数
    • 析构函数
      • 概念
      • 特征
    • 拷贝构造函数
      • 特征
    • 运算符重载
      • == 、 >、 <=
      • +=
      • +
      • 赋值重载
      • Date类的完善
        • 构造函数的完善
        • +=、-=的完善
        • 用+复用+=
        • -、-=以及-和-=的相互复用
      • 前置++、--
      • 后置++、--
      • 流插入、流提取
    • 取地址重载
  • const成员

类的6个默认成员函数

默认成员函数:不写编译器也会默认生成一份
在这里插入图片描述

构造函数

自己写的构造函数

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任
并不是开空间创建对象,而是初始化对象
其特征如下:

  1. 函数名与类名相同。
  2. 无返回值,不需要写void
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载。
  5. . 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦
    用户显式定义编译器将不再生成。
  6. 关于编译器生成的默认成员函数,很多童鞋会有疑惑:不实现构造函数的情况下,编译器会
    生成默认的构造函数。但是看起来默认构造函数又没什么用?d对象调用了编译器生成的默
    认构造函数,但是d对象_year/_month/_day,依旧是随机值。也就说在这里编译器生成的
    默认构造函数并没有什么用??
    解答:C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类
    型,如:int/char…,自定义类型就是我们使用class/struct/union等自己定义的类型,看看
    下面的程序,就会发现编译器生成默认的构造函数会对自定类型成员_t调用的它的默认成员
    函数。
  7. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
    注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为
    是默认构造函数。
#include <iostream>
using namespace std;

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

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _day;
	int _month;
	int _year;
};

int main()
{
	Date d1;
	Date d2(2023, 1, 24);
	d1.Print();
	d2.Print();

	return 0;
}

在这里插入图片描述

对于没有参数的初始化对象时,不能写成下面那样,因为无法与函数声明区分
Date d1()

也可以用缺省函数,下面两个函数构成函数重载,但是无参调用的时候会产生歧义

//Date()
//	{
//		_day = 1;
//		_month = 1;
//		_year = 1;
//	}
	Date(int day = 1, int month = 1, int year = 1)
	{
		_day = day;
		_month = month;
		_year = year;
	}

默认生成的构造函数

默认构造函数:编译器默认生成的、无参的构造函数、全缺省的构造函数(可以不传参的都叫默认构造),这三个函数不能同时存在,因为会存在调用歧义。
如果不写构造函数,有没有构造函数
默认生成的,但此时是随机值

class Date
{
public:
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _day;
	int _month;
	int _year;
};

int main()
{
	Date d1;
	d1.Print();

	return 0;
}

在这里插入图片描述
对于栈的初始函数来说,初始化的也是随机值

class Stack
{
public:

private:
	int* _a;
	int _top;
	int _capacity;
};

int main()
{
	Stack s1;

	return 0;
}

在这里插入图片描述
但对于像MyQueue的构造函数就初始化了
在这里插入图片描述

在这里插入图片描述
规则
内置类型:int/double/…指针,eg:Date* p是内置类型
自定义类型: class struct…
默认生成的构造函数,对于内置类型成员不做处理(看编译器,建议当成不处理),自定义类型会取调用它的默认构造(调用无参的默认构造,如果自定义类型没有默认构造 - 初始化列表,类和对象下讲)
对于这个缺陷C++11提供如下解决方法,下面这个写法还是声明,给的缺省值
在这里插入图片描述

析构函数

概念

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由
编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

特征

析构函数是特殊的成员函数,其特征如下:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值类型。
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构
    函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
  5. 编译器生成的默认析构函数,对自定类型成员调用它的析构函数。
  6. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如
    Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类
    日期类不需要写析构,栈需要写析构
class Date
{
public:
	Date(int day = 1, int month = 1, int year = 1)
	{
		_day = day;
		_month = month;
		_year = year;
	}

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	~Date()
	{
		cout << "~Date()" << endl;
	}
private:
	int _day = 1;
	int _month = 1;
	int _year = 1;
};


int main()
{
	Date d1;
	d1.Print();

	return 0;
}

在这里插入图片描述
在这里插入图片描述

拷贝构造函数

在这里插入图片描述
浅拷贝时,st和st1对象会导致对同一块空间的重复释放
解决方法:自定义类型对象拷贝时,调用一个函数,这个函数就叫拷贝构造 - 深拷贝。
(1)传参的时候
(2)初始化构造的时候Date d2(d1)

特征

  1. 拷贝构造函数是构造函数的一个重载形式
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错
    因为会引发无穷递归调用。.0
  3. 默认生成的拷贝构造函数:对内置类型会完成值拷贝,自定义对象回去调用它的拷贝对象。
    在这里插入图片描述
    像下面所示,st1与st中的_a是指向同一块空间,当这两个对象被释放时,会对_a所指的这段空间释放两次,从而造成错误,拷贝构造主要是解决这个问题的深拷贝
    在这里插入图片描述
    在这里插入图片描述
class Stack
{
public:
	Stack()
	{
		//...
	}
	Stack(const Stack& stt)
	{
		_a = (int*)malloc(sizeof(int) * stt._capacity);
		if (_a == nullptr)
		{
			perror("malloc fail");
			exit(-1);
		}
		memcpy(_a, stt._a, sizeof(int) * stt._top);
		_top = stt._top;
		_capacity = stt._capacity;
	}
	~Stack()
	{
		cout << "~Stack()" << endl;
	}
private:
	int* _a;
	int _top;
	int _capacity;
};

在这里插入图片描述

1、被拷贝的对象前面加const,防止意外的改变

运算符重载

双操作数的运算符,第一个参数是左操作数,第二个参数是右操作数
对于+、-、*、/、>、<等等,内置类型可以直接使用,自定义类型无法使用
解决方法:(1)写一个函数 (2)使用运算符重载
运算符重载:operator+运算符 ,使用方法:直接使用运算符

函数重载:允许参数不同的同名函数存在
运算符重载:自定义类型可以直接使用运算符

不能通过连接其他符号来创建新的操作符:比如operator@
重载操作符必须有一个类类型参数
用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
.*
::
sizeof
?:
. 注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

== 、 >、 <=

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	
public:
	int _year;
	int _month;
	int _day;
};
bool operator==(Date x, Date y)
{
	return x._year == y._year && x._month == y._month && x._day == y._day;
}
bool operator>(Date x, Date y)
{
	if (x._year > y._year)
		return true;
	else if (x._year == y._year && x._month > y._month)
		return true;
	else if (x._year == y._year && x._month == y._month && x._day > y._day)
		return true;
	return false;
}
bool operator<=(Date x, Date y)
{
	return ~(x > y);
}

int main()
{
	Date d1(2001, 3, 29);
	Date d2(2024, 3, 1);
	cout << (d1 > d2) << endl;
	cout << (d1 == d2) << endl;
	cout << (d1 <= d2) << endl;
	return 0;
}

在这里插入图片描述
报错的原因:因为流提取运算符的优先级大于>,因此加个括号就没事了
在这里插入图片描述
**此时程序的缺陷 :
1、运算符重载函数的参数那,调用了拷贝构造 --> 用&
2、为了在函数里访问类的成员变量,把成员变量设置 成了公有 --> 在类里面设置一些访问成员的函数;将运算符重载函数放到类里面
**
缺陷1修改

bool operator==(const Date& x, const Date& y)
{
	return x._year == y._year && x._month == y._month && x._day == y._day;
}
bool operator>(const Date& x, const Date& y)
{
	if (x._year > y._year)
		return true;
	else if (x._year == y._year && x._month > y._month)
		return true;
	else if (x._year == y._year && x._month == y._month && x._day > y._day)
		return true;
	return false;
}
bool operator<=(const Date& x, const Date& y)
{
	return ~(x > y);
}

缺陷2修改

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

	bool operator==(const Date& y)
	{
		return _year == y._year && _month == y._month && _day == y._day;
	}
	bool operator>(const Date& y)
	{
		if (_year > y._year)
			return true;
		else if (_year == y._year && _month > y._month)
			return true;
		else if (_year == y._year && _month == y._month && _day > y._day)
			return true;
		return false;
	}
	bool operator<=(const Date& y)
	{
		return ~(*this > y);
	}
	
private:
	int _year;
	int _month;
	int _day;
};

在这里插入图片描述
也可以d1.operator>(d2)这样显示的调用
这个类还可以些哪些运算符重载,这个取决于哪些运算符对于这个类是有意义的
eg:日期-日期、日期+=天数、日期+天数

+=

int GetMonthDay(int year, int month)
	{
		assert(year >= 1 && month >= 1 && day >= 1);
		int arr[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))
			return 29;
		return arr[month];

	}

Date& operator+=(int day)
	{
		_day += day;
		while (_day > GetMonthDay())
		{
			_day -= GetMonthDay();
			_month++;
			if (_month > 12)
			{
				_year++;
				_month = 1;
			}

		}
		return *this;

	}

细节
根据内置类型的定义,+=是有返回值的,因此自定义类型也应该有返回值
在这里插入图片描述

在这里插入图片描述

+

int GetMonthDay(int year, int month)
	{
		assert(year >= 1 && month >= 1 && day >= 1);
		int arr[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))
			return 29;
		return arr[month];

	}
Date operator+(int day)
	{
		Date tmp(*this);
		tmp._day += day;
		while (tmp._day > GetMonthDay(tmp._year, tmp._month))
		{
			tmp._day -= GetMonthDay(tmp._year, tmp._month);
			tmp._month++;
			if (tmp._month > 12)
			{
				tmp._year++;
				tmp._month = 1;
			}

		}
		return tmp;

	}

赋值重载

operator= 我们不写,编译器回生成默认的operator=。跟拷贝构造的行为类似,内置类型值拷贝,自定义类型调用他的赋值
Date、MyQueue可以不用写,默认生成的operator=就可以用
赋值重载:(重载运算符)两个已经存在的对象拷贝
拷贝构造:一个已经存在的对象去拷贝初始化另一个对象

缺省参数不能同时出现在声明与定义里面,只能在声明中定义

Date& operator=(const Date& y);

Date& Date::operator=(const Date& y)
{
	if (this != &y)
	{
		_year = y._year;
		_month = y._month;
		_day = y._day;
	}

	return *this;
}

Date类的完善

构造函数的完善
Date::Date(int year = 1, int month = 1, int day = 1)
{
	_year = year;
	_month = month;
	_day = day;

	if (_year < 1 || _month > 13 || _month < 1 || day < 1 || day > GetMonthDay(_year, _month))
	{
		print();
		cout << "日期非法" << endl;
	}
}
+=、-=的完善

如果+=、-=一个负的天数那么就会报错

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)
{
	if (day < 0)
	{
		return *this += (-day);
	}
	_day -= day;
	while (_day < 1)
	{
		_month--;
		if (_month < 1)
		{
			_year--;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}
用+复用+=

复用1

Date& Date::operator+=(int day)
{
	*this = *this + day;
	return *this;

}
Date Date::operator+(int day)
{
	Date tmp(*this);
	tmp._day += day;
	while (tmp._day > GetMonthDay(tmp._year, tmp._month))
	{
		tmp._day -= GetMonthDay(tmp._year, tmp._month);
		tmp._month++;
		if (tmp._month > 12)
		{
			tmp._year++;
			tmp._month = 1;
		}

	}
	return tmp;

}

在这里插入图片描述

复用2

Date& Date::operator+=(int 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)
{
	Date tmp(*this);
	
	tmp += day;
	return tmp;

}

在这里插入图片描述

复用2要比复用1效率更高

-、-=以及-和-=的相互复用
Date& operator-=(int day);
Date operator-(int day);

Date& Date::operator-=(int day)
{
	_day -= day;
	while (_day < 1)
	{
		_month--;
		if (_month < 1)
		{
			_year--;
			_month = 12;
		}
		_day += GetMonthDay(_year, _month);
	}
	return *this;
}
Date Date::operator-(int day)
{
	Date tmp(*this);
	tmp -= day;
	return tmp;
}

前置++、–

Date& operator++();
Date& operator--();

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

Date& Date::operator--()
{
	*this -= 1;
	return *this;
}

注意:前置++、–的效率会比后置++、–的效率高

后置++、–

难点:如何声明后置++、–
函数名相同、参数不同,所以必须和前置++、–构成函数重载,加一个参数,int i(祖师爷规定的,i可写可不写,形参没有用所以一般不写)
后置效率多,多拷贝构造了两次

Date& operator++(int);
Date& operator--(int);

Date& Date::operator++(int)
{
	Date tmp(*this);
	*this += 1;
	return tmp;
}

Date& Date::operator--(int)
{
	Date tmp(*this);
	*this -= 1;
	return tmp;
}

流插入、流提取

cin是istream的类
cout是ostream的类
io流可以识别不同的类型,原因:函数重载参数识别
在这里插入图片描述
写法一:

void operator<<(ostream& out);

void Date::operator<<(ostream& out)
{
	out << _year << "年" << _month << "月" << _day << endl;
	return;
}

在这里插入图片描述

这样写的问题:
对于成员函数,默认左操作数为第一个参数,这样就造成了流插入的可读性不好
解决方法:
实现到全局

方法二
将<<、>>流运算符实现到全局,这样才能让流对象做第一个参数,符合可读性
实现到全局,对于私有的成员变量就没法访问了=>将函数写成友元函数
在这里插入图片描述

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1);
	void print();

	int GetMonthDay(int year, int month);
    friend void operator<<(ostream& out, const Date& y);
private:
	int _year;
	int _month;
	int _day;
};

void operator<<(ostream& out, const Date& y);
void operator<<(ostream& out, const Date& y)
{
	out << y._year << "年" << y._month << "月" << y._day << endl;
	return;
}

**问题:**没法联系的插入,返回值出现了错误,返回值应该是ostream类型的对象
在这里插入图片描述

friend ostream& operator<<(ostream& out, const Date& y);

ostream& operator<<(ostream& out, const Date& y)
{
	out << y._year << "年" << y._month << "月" << y._day << endl;
	return out;
}
friend istream& operator>>(istream& in, Date& y);

istream& operator>>(istream& in, Date& y)
{
	in >> y._year >> y._month >> y._day;
	return in;
}

分析:
流本质是为了解决,自定义类型的输入和输出问题
printf scanf无法解决自定义类型的输入输出问题

取地址重载

取地址重载不写的话,编译器也会自动生成。一般自动生成的就够用了,因为取地址重载也写不出什么花来。
如果不想让使用者取地址的话,可以自己写取地址重载,返回空指针。

Date* operator&();
const Date* operator&() const;


Date* Date::operator&()
{
	return this;
}

const Date* Date::operator&() const
{
	return this;
}

const成员

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改
对于一个const对象是没法调用非const的成员函数,因为权限放大问题
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
解决方法:给this这个对象加上const
const对象和非const对象都可以调用const成员函数
const成员函数声明定义都得写

void print() const;

void Date::print() const
{
	cout << _year << "-" << _month << "-" << _day << endl;
}

const成员函数定义原则
1、能定义成const的成员函数都应该定义成const,这样const对象(权限平移)和非const对象(权限缩小)都可以调用
2、要修改成员变量的成员函数,不能定义成const

bool operator==(const Date& y) const;
	bool operator>(const Date& y) const;
	bool operator>=(const Date& y) const;
	bool operator<(const Date& y) const;
	bool operator<=(const Date& y) const;
	bool operator!=(const Date& y) const;

	Date& operator+=(int day);
	Date operator+(int day) const;
	Date& operator=(const Date& y);
	Date& operator-=(int day);
	Date operator-(int day) const;
	int operator-(const Date& y) const;
	Date& operator++();
	Date& operator--();
	Date& operator++(int);
	Date& operator--(int);

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

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

相关文章

安康杯安全知识竞赛上的讲话稿

各位领导、同志们&#xff1a; 经过近半个月时间的准备&#xff0c;南五十家子镇平泉首届安康杯安全生产知识竞赛初赛在今天圆满落下帏幕&#xff0c;经过紧张激烈的角逐&#xff0c; 代表队、 代表队和 代表队分别获得本次竞赛的第一、二、三名让我们以热烈的掌声表示祝…

TensorRT是什么,有什么作用,如何使用

TensorRT 是由 NVIDIA 提供的一个高性能深度学习推理&#xff08;inference&#xff09;引擎。它专为生产环境中的部署而设计&#xff0c;用于提高在 NVIDIA GPU 上运行的深度学习模型的推理速度和效率。以下是关于 TensorRT 的详细介绍&#xff1a; TensorRT 是 NVIDIA 推出的…

容器: string

引言: 为什么要有string类型, 就使用字符数组表示字符串不行吗? 原因: 使用字符数组描述文本信息, 无法确定开多大空间, 开多了浪费,开少了不够用使用string封装: 扩容机制:减少了空间的浪费各种接口:方便修改等操作 string的使用 容量相关 size:获取字符个数,不包含\0 (C语言…

IOS苹果通话记录在线生成网站源代码,直接上传就可使用

一键生成&#xff0c;PHP的上传到网站根目录打开域名访问即可 源码免费下载地址专业知识分享社区-专业知识笔记免费分享 (chaobiji.cn)

Mocha and Railgun(几何规律)

链接&#xff1a;https://ac.nowcoder.com/acm/contest/33186/D 来源&#xff1a;牛客网 题目描述 There is a candy store near Mochas school. Its said that the storekeeper, Dagashiya, can cast the railgun spell. To be the most powerful Mahou Shoujo, Mocha ask…

118.龙芯2k1000-pmon(17)-制作ramdisk

目前手上这个设备装系统不容易&#xff0c;总是需要借助虚拟机才能实现。 对生产就不太那么友好&#xff0c;能否不用虚拟机就能装Linux系统呢&#xff1f; 主要是文件系统的问题需要解决&#xff0c;平时我们一般是用nfs挂载后&#xff0c;然后对硬盘格式化&#xff0c;之后…

社区服务类创业项目推荐:抓住社区商业新机遇

大家好&#xff0c;我是一名90后鲜奶吧创业者&#xff0c;目前在社区经营5年时间&#xff0c;今天我想和大家分享一些关于社区服务类创业项目的推荐&#xff0c;都是这么多年我见证过生意最好的店面。 1、社区便利店&#xff1a; 随着人们生活节奏的加快&#xff0c;对便利购…

【Linux实践室】Linux常用命令:文件操作|文件夹操作

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;Linux实践室、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️任务描述二. ⛳️相关知识2.1 &#x1f514;Linux文件操作2.1.1 &#x1f47b;创建文件2…

数组连续和 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 给定一个含有N个正整数的数组&#xff0c;求出有多少连续区间&#xff08;包括单个正整数&#xff09;&#xff0c;它们的和大于等于 x。 输入描述 第一行为两个…

Linux——进程信号(一)

目录 1、信号入门 1.1、技术应用角度的信号 1.2、注意 1.3、信号概念 1.4、用kill -l命令可以查看系统定义的信号列表 1.5、信号处理常见方式概览 2、产生信号 2.1通过终端按键产生信号 Core Dump 2.2、调用系统函数向进程发信号 2.3、由软条件产生信号 3、总结思考…

华为北向网管NCE开发教程(2)REST接口开发

华为北向网管NCE开发教程&#xff08;1&#xff09;闭坑选接口协议 华为北向网管NCE开发教程&#xff08;2&#xff09;REST接口开发 华为北向网管NCE开发教程&#xff08;3&#xff09;CORBA协议开发 假设你现在要开始华为北向接口REST协议之前&#xff0c;需要准备如环境 1准…

学习与学习理论 - 2024教招 - test

一 方向 方向性很重要&#xff0c;像学投篮一样关注发力顺序才是关键出发点&#xff0c;如果这个出发点没确定下来&#xff0c;会走许多弯路。所有学习理论大的观点&#xff0c;到某个人物个人的观点。被干掉之前&#xff08;不能被干掉&#xff09;&#xff0c;掌握所需的知识…

C++:Stack和Queue的模拟实现

创作不易&#xff0c;感谢三连&#xff01; 一、容器适配器 适配器是一种设计模式(设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结)&#xff0c;该种模式是将一个类的接口转换成客户希望的另外一个接口。 就如同是电源适配器将不适用的交流电…

STM32CubeMX学习笔记13 ---IIC总线

1、IIC 简介 IIC(Inter&#xff0d;Integrated Circuit)总线是一种由NXP&#xff08;原PHILIPS&#xff09;公司开发的两线式串行总线&#xff0c;用于连接微控制器及其外围设备。多用于主控制器和从器件间的主从通信&#xff0c;在小数据量场合使用&#xff0c;传输距离短&…

《汇编语言》- 读书笔记 - 第17章-实验17 编写包含多个功能子程序的中断例程

《汇编语言》- 读书笔记 - 第17章-实验17 编写包含多个功能子程序的中断例程 逻辑扇区根据逻辑扇区号算出物理编号中断例程&#xff1a;通过逻辑扇区号对软盘进行读写 代码安装 int 7ch 测试程序效果 实现通过逻辑扇区号对软盘进行读写 逻辑扇区 计算公式: 逻辑扇区号 (面号*8…

【PCIe 链路训练】之均衡(equalization)

1、概述 这篇文章简单介绍一下PCIE phy的均衡原理和过程,USB phy,ethernet phy这些高速的串行serdes也有相同或者相似的结构。可以不用太关注其中的细节,等到debug的时候可以查询协议,但是需要了解这个故事讲的大概内容。整个equalization过程是controller和phy一起配合完成…

喜报|炼石免改造数据安全入选上海网安产业创新大会优秀案例

近日&#xff0c;上海网络安全产业创新大会隆重召开&#xff0c;上海普陀区委副书记、区长肖文高&#xff0c;上海市经济和信息化委员会总工程师葛东波出席并致辞&#xff0c;普陀区副区长肖立出席。大会以“产业赋能、生态打造”为主题&#xff0c;为发掘数据安全领域的优秀产…

【代码随想录算法训练营Day29】 491.递增子序列;46.全排列;47.全排列 II

文章目录 ❇️Day 29 第七章 回溯算法 part05✴️今日内容❇️491.递增子序列自己的思路随想录思路自己的代码 ❇️46.全排列思路代码流程 ❇️47.全排列 II思路代码 ❇️Day 29 第七章 回溯算法 part05 ✴️今日内容 491.递增子序列46.全排列47.全排列 II ❇️491.递增子序…

低压MOS在步进电机驱动器上的应用-REASUNOS瑞森半导体

一、前言 步进电机驱动器是一种用于控制步进电机运动的装置&#xff0c;它是将控制信号转换成步进电机可以识别的控制电压或电流的电路。它在工业自动化领域有着广泛的应用&#xff0c;如机器人、印刷机、木工机床、喷绘机等。步进电机驱动器的组成结构主要由以下部分&#xf…