【C++初阶】类和对象(一)

news2024/11/25 7:13:26

在这里插入图片描述

​📝个人主页:@Sherry的成长之路
🏠学习社区:Sherry的成长之路(个人社区)
📖专栏链接:C++初阶
🎯长路漫漫浩浩,万事皆有期待

上一篇博客:【C++初阶】C++入门(一):命名空间&&C++的输入输出&&缺省参数&&函数重载

文章目录

  • 1.面向过程和面向对象
  • 2.类的定义
    • 2.1 类的定义方式
  • 3.类的访问限定符及封装
    • 3.1封装的特性:
      • 3.1.1访问限定符
      • 3.1.2封装
  • 4.类的作用域
  • 5.类的实例化
  • 6.类对象
    • 6.1类对象大小
    • 6.2类对象存储方式
  • 7.this 指针
    • 7.1 引入
    • 7.2 特性
    • 7.3 考题
    • 7.4 优点
  • 8.总结:

1.面向过程和面向对象

C语言是面向过程的,关注的是过程,分析求解问题的步骤,通过函数调用逐步解决问题
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成

两种思想的设计方式截然不同,例如设计简单外卖系统:
请添加图片描述
面向过程:关注实现下单、接单、送餐等过程。体现到代码层面就是函数(方法),总体关注过程

面向对象:关注实现类对象及类对象间的关系。用户,商家,骑手,以及他们之间的关系,提现到代码层面就是类的设计和类之间的关系

C++是基于面向对象的语言:它可以面向过程和面向对象混编,原因是 C++ 兼容 C
但是对于 java 等纯面向对象语言:只有面向对象 。

2.类的定义

C++ 中定义类有两个关键字 struct/class .

struct Stu
{
	char name[10];
	int age;
	int id;
};

class cl
{
	char id[10];
	char teacher[8];
	int tage;
};

C++ 兼容 C 中结构体的用法,同时 struct 在 C++ 中也升级成了类 。

在 C 中创建结构体局部变量,需要写成:

struct Stu s1;

但是升级为类之后,Stu 就直接变为类的名称,当定义局部变量时,可以写为 Stu s2 ;但是也可以像上面那么写,因为 C++ 是兼容 C 的。

struct Stu s1; // 兼容 c 
Stu s2; // 升级到类,Stu 为类名,也是类型

同样,对它们进行访问也没问题

C++中的 struct(类)和结构体不同的是:除了可以定义成员变量还可以成员函数,成员函数可以访问成员变量,但是如果成员函数中的形参和成员变量相同 ,就像这样:

struct Stu
{
	char name[10];
	int age;
	int id;

	void init(const char* name, int age, int id) {}
};

但这样分不清形参和成员变量,所以C++引入 ‘_’ 定义变量名,以作区分:

struct Stu
{
	char _name[10];
	int _age;
	int _id;
	
	void init(const char* name, int age, int id) {}
};

由于C++是面向对象的,所以一般把定义的变量叫做对象 ,虽然变量也对,但是最好叫对象。应用我们学的知识简单写一个类:

struct Stu
{
	char _name[10];
	int _age;
	int _id;

	void init(const char* name, int age, int id) 
	{
		strcpy(_name, name);
		_age = age;
		_id = id;
	}

	void print()
	{
		cout << _name << endl;
		cout << _age << endl;
		cout << _id << endl;
	}
};

int main()
{
	struct Stu s1;
	Stu s2;

	s1.init("sherry", 19, 1);
	s2.init("kathy", 20, 2);

	s1.print();
	s2.print();
	
	return 0;
}

但上面结构体的定义,在C++中更喜欢用class来代替。

其中class为定义类的关键字,className为类的名字,{}中为类的主体,注意定义结束时加上后面的分号;

 类中的元素称为类的成员:类中的数据称为类的属性或者成员变量,类中的函数称为类的方法或者成员函数。

2.1 类的定义方式

1、声明和定义全部放在类体中。需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。(cpp规定)
在这里插入图片描述

2、声明放在头文件(.h)中,定义放在源文件(.cpp)中。
在这里插入图片描述

注意:一般情况下,更期望采用第二种方式。

3.类的访问限定符及封装

C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。

面向对象的三大特性:封装继承多态

3.1封装的特性:

在类中,类的数据和方法都放到一起
而访问限定符是封装的一个很厉害的特性,基于访问限定符,可以对 对象 进行 严格管控

3.1.1访问限定符

在这里插入图片描述

访问限定符说明:

1.public修饰的成员在类外可以 直接被访问
2.protected 和 private 修饰的成员在类外不能直接被访问(类似,等学到继承时区分不同)
3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4.如果后面没有访问限定符,作用域就到 } 即类结束。
5.class的默认访问权限为privatestructpublic(因为struct要兼容C)
6.默认访问限定符,即不写时,类中的默认访问权限;一般在定义类时,建议明确定义访问限定符 ,不要用 class/struct的默认限定
7.访问限定符是约束外面的,对于类中,则没有限定,类里面可以全局访问。

注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

3.1.2封装

封装就是让数据和方法放在一起,进行 更好 的管理。对于 C 是不封装的,是一种较 松散 的管理。C++ 是将数据和方法封装到类里面,C 是数据和方法分离的(数据访问控制是自由的,不受限制的)

那么C++ 如何进行严格管理?假设定义一个栈:

class Stack
{
private:
	int* _a;
	int _top;
	int _capacity;
public:
	void Init()
	{
		_a = nullptr;
		_top = _capacity;
	}
	void Push() {}
	void Pop() {}
	void Top() {}
};

int main()
{
    Stack st1;
    Stack st2;
    st1.Push();
    st2.Pop();
}

如果对于 C 语言,进行 取top 其实可以有两种方式,就像我们实现的 栈 一样,
1.可以通过下标(st2.a[s._top-1];)进行访问;2.也可以调用 top接口[int top=st2.Top();]放元素

但是像1.这种松散的方式,若不清楚 Stack 本身的状况贸然使用 很容易出错 ,就比如博客顺序栈的C语言实现中的 top 有两个位置,一不小心就会使用出错,访问出界到随机值。

C语言只是推荐调用接口函数,并没有起到强制性的管理作用,如果硬是要强行访问结构,很容易出现问题

但如果 C++ 将结构部分 定义成私有 ,方法定义成共有 ,进行严格管理,就不会出现之前的情况。就比如:

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

这些是被 private 修饰,封装在类里面的,如果直接进行操作,即访问结构,就会报错,因为这时成员变量为私有,不让访问 。

总结:封装就是数据和方法都封装到类里,能访问定义成共有;不能访问定义成私有。
在C++语言中实现封装,可以通过类将数据以及操作数据的方法进行有机结合,通过访问权限来隐藏对象内部实现细节,控制哪些方法可以在类外部直接被使用。

4.类的作用域

class Person
{
public:
	//显示基本信息
	void ShowInfo();
private:
	char* _name;  //姓名
	char* _sex;   //性别
	int _age;     //年龄
};

//这里需要指定ShowInfo是属于Person这个类域
void Person::ShowInfo()
{
	cout << _name << "-" << _sex << "-" << _age << endl;
}

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用“::”作用域解析符指明成员属于哪个类域。

5.类的实例化

用类类型创建对象的过程,称为类的实例化。

类是对 对象 进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它 。

一个类可以实例化多个对象:就好比类是图纸,根据图纸可以建造出多个楼房
在这里插入图片描述

设计图只设计出需要什么东西,但是并没有实体的建筑存在。同样类也只是一个设计,只有实例化出的对象才能实际存储数据,占用物理空间。

对于类创建出来的对象,可以访问类中成员;但是对于类本身,是不能访问成员与方法的

所以对于类仅仅起 描述作用 而已,真正使用还是要类对象 。我们可以认为类这些代码存在代码段,是公共的。

6.类对象

6.1类对象大小

一个类当中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?类的大小又是如何计算的呢?

class Stack
{
public:
	void Init();
	void push(int x);
	// ... 
private:
	int* _a;
	int _capacity;
	int _top;
};

6.2类对象存储方式

猜测一:对象中包含类的各个成员
在这里插入图片描述

缺陷: 每个对象中成员变量是不同的,但是调用同一份函数,如果按照此种方式存储,当一个类创建多个对象时,每个对象中都会保存一份代码,相同代码保存多次,浪费空间。

猜测二:只保存成员变量,成员函数存放在公共的代码段。
在这里插入图片描述

对于类中成员变量,独立保存起来;但是类中成员函数就和普通的函数一样存在于公共代码区,即代码段,也就是常量字符串存储地,这里存在代码段的含义就是:函数被编译后的指令存在于代码段。

对于上述两种存储方式,计算机是按照哪种方式来存储的,我们可以通过对下面的不同对象分别获取大小来进行分析:

// 类中既有成员变量,又有成员函数
class A1 {
public:
	void f1(){}
private:
	int _a;
};
// 类中仅有成员函数
class A2 {
public:
	void f2() {}
};
// 类中什么都没有---空类
class A3
{};

通过sizeof来获取这三个对象的大小,结果A1的大小为4个字节,A2的大小为1个字节,A3的大小也为1个字节。

对于空类和只有成员函数的类也有自己的地址,并不是空,所以一定有大小,编译器给了空类 1 字节来唯一标识空类(当然也有类的大小也为1,具体看实现)

这 1 字节是为了占位,并不存储有效数据,标识对象被实例化定义了,表示存在 。

1.类中只计算成员变量的大小,计算方式满足C语言结构体内存对齐,详细可以跳转 1.6 结构体内存对齐
2.空类和只具有成员函数的类大小为 1

总结:计算类或类对象的大小,只看成员变量,并考虑内存对齐,C++内存对齐规则跟 C 结构体一致。而类中成员函数就和普通的函数一样存在于公共代码区。

7.this 指针

7.1 引入

先写出一个日期类:

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

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

private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	d1.Init(2023, 1, 31);
	d1.Print();

	Date d2;
	d2.Init(2023, 2, 1);
	d2.Print();

	return 0;
}

上述代码调用成员函数传参时,看似只传入了一些基本数据,实际上还传入了指向该对象的指针:
在这里插入图片描述
编译器进行编译时,看到的成员函数实际上也和我们所看到的不一样,每个成员函数的第一个形参实际上是一个隐含的this指针,该指针用于接收调用函数的对象的地址,用this指针就可以很好地访问到该对象中的成员变量。

上面讲过 类的实例化 后,我们知道类实例化处的每个对象是独立的,所以对象的成员变量是独立的,但是多个类对象都使用共同的成员函数 :

我们调试起来转到反汇编看一下:

在这里插入图片描述

看到 call 指令这一行,发现函数的地址是相同的,也印证了我们的说法:不同对象使用相同成员函数。

7.2 特性

但是有个问题,就拿 Print 函数来说,当 d1 调用 Print 函数时,打印的是 d1 的成员变量;当 d2 调用时,打印的是 d2 的成员变量。而类对象中的成员变量是独立的,如何做到每次调用都可以输出正确的成员变量的?

这就依靠的是 this 指针 :
1.对于 d1._year ,即对象访问成员变量,意义是在类对象这块空间中,访问到 _year 这个成员变量,对其进行操作

2.而对于 d1.Print() ,则是访问成员函数,是到公共区域代码段上找到成员函数,找到变为 call 指令,进行调用,这里有两层,第一层就是我们前面说的;第二层就是 this 指针

当代码被编译之后,编译器会对成员函数进行处理,例如这里的 Print 函数,就有一个隐藏的 this 指针 ,类似:

void Print(Date* const this) // const 是因为 this 指针不可改,this 是指针,所以直接用 const 修饰 this 
{
    cout << this->year << "-" << this->_month << "-" << this->_day << endl;
}

// 调用 
d1.Print(&d1);

当不同的对象调用时,根据传过来的地址,this 指针会指向不同的对象

但是注意一点,虽然原理是这样,但是我们不能这么写,例如 d1.Print(&d1) 就会报错,因为 this 指针是隐藏的,统一规定就别写,由此提炼出两点:

1.调用成员函数时,不能显示传实参给 this
2.定义成员函数时也不能声明形参 this

即形参和实参不能写,但是在成员函数中,是可以显示写的,但是很少用:

cout << this->year << "-" << this->_month << "-" << this->_day << endl;

甚至打印 this 指针也是可以的:

void Print(Date* const this) // const 是因为 this 指针不可该,this 是指针,所以直接用 const 修饰 this 
{
    cout << this << endl;
    cout << this->year << "-" << this->_month << "-" << this->_day << endl;
}

这里打印的 this 指针的地址:就是对应对象的地址。但是我们一般不这么写,在一些场景下,需要显示用 this ,这个我们之后再看。

this 指针在哪里?一般情况下在栈区,因为 this 指针是隐含的形参,this 指针并不在对象中 ,所以指针跟普通指针参数一样存在函数调用的栈帧里面。而 this 指针不需要处理,一般会直接转换为指令,我们不用担心。

但是有时也会特殊处理:

在这里插入图片描述

在 vs 下,有些情况会将对象的地址(即 this 指针)放到寄存器 ecx 中,因为在调用成员函数时 this 指针要被经常使用(this->_year)。

7.3 考题

接下来,通过这几个题目看看对于类的理解

q1 :

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
	void PrintA()
	{
		cout << "Print()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->Print();
	return 0;
}

q2 :

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
	void PrintA()
	{
		cout << _a << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	p->PrintA();
	return 0;
}

q3:

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
	void PrintA()
	{
		cout << "PrintA()" << endl;
	}
private:
	int _a;
};
int main()
{
	A* p = nullptr;
	(*p).PrintA();
	return 0;
}

你可能看到指针p是一个空指针,而q1代码和q2代码都通过操作符“->”,间接性的执行了对p的解引用操作,所以可能会认为程序崩溃。但其实并不是

答案揭晓:

q1 :C 正常运行

q2:B 运行奔溃

q3:C 正常运行

可是,为什么?
在这里插入图片描述

q1分析:
在这里插入图片描述

Print() 是成员函数,成员函数在代码段,在公共区域;虽然 p 是空指针,但是访问公共区域并不会报错,因为不需要到对象里面找。

调用函数,会把 p 当做 this 指针传过去,在 Print() 函数中,并没有解引用,所以没有问题,只不过此刻的 this 指针为空而已。

指针p确实是一个类的空指针,但当执行第一句代码时,程序并不会崩溃。第一句代码并没有对空指针p进行解引用,因为Print() 是成员函数,地址并没有存到对象里面,成员函数的地址是存在公共代码段的。

注意
这里可以定义变量访问 Print 函数,也可以用指针,例如 d.Print(); 和 p->Print(); 都是可以的;但是千万不要写成 Print(); 的形式,因为类是有作用域的,在调用函数时,只会默认在全局找,得规定在哪个类中,二是因为 this 指针的问题,因为此刻没有对象,this 指针也不清楚,所以这样是错误的.

q2 分析:

同理 Print() 在公共区域,所以调用时是没有问题的,问题在于当 this 指针传递过去后,函数中是这样的:cout << _a << endl; 这里实际上为 cout << this->_a << endl ,对空指针进行了解引用,这就崩溃了。

当程序执行第二句代码时,会因为内存的非法访问而崩溃。执行第二句代码时,调用了成员函数Print,这里并不会产生什么错误(理由同上),但是Print函数中打印了成员变量_a,成员变量_a只有通过对this指针进行解引用才能访问到,而this指针此时接收的是nullptr,对空进行解引用必然会导致程序的崩溃。

q3 分析:

Print() 是公共的,不在对象里面;这里表面上看 (*p).Print() 是对空指针进行解引用了,其实并没有,编译器对其进行了处理,这里是把 p 传递给了 this ,而这里本质上和 p->Print() 是相同的

总结:这里的崩溃与否取决于访问的东西是否在对象中,如果访问的是公共区域,那么就再看传递的 this 指针为空指针时,会不会对 对象 进行解引用。

7.4 优点

而this指针的存在就像自动挡和手动挡的区别,方便我们使用
在这里插入图片描述
优点:解决1.初始化和销毁经常忘记 2.有些地方写起来很繁琐 的问题

8.总结:

今天我们初识了面向过程和面向对象,了解了什么是类,认识并具体学习了有关类的命定义、访问限定符及封装、作用域、实例化、类对象的知识。接下来,我们将继续学习类和对象的相关知识。希望我的文章和讲解能对大家的学习提供一些帮助。

当然,本文仍有许多不足之处,欢迎各位小伙伴们随时私信交流、批评指正!我们下期见~

在这里插入图片描述

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

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

相关文章

一文看懂低代码,5分钟从入门到原理全搞定

全球低代码市场已经走过了近20年&#xff0c;中国低代码市场近5年经历了百花齐放的广泛探索阶段&#xff0c;更旺盛的市场需求逐步在被激发。现在&#xff0c;让我们按下暂停键&#xff0c;看看这些产品给我们呈现了低代码市场一幅怎样的百景图。 低代码平台简介 广义上的低代…

[nesbot/carbon]轻松优雅的驾驭时间处理

简介 这个库的名字其实就很有意思&#xff1a;“carbon”&#xff0c;是化学元素的名字“碳”&#xff0c;为什么叫这个名字呢&#xff1f;在科学界&#xff0c;有一个"放射性碳定年法"的东西&#xff0c;是一种利用碳的同位素14C的放射性来对含有有机物质的物品进行…

废物,我TMD一个985却斗不过专科生(大厂自动化测试2年被裁)

前言 看到标题&#xff0c;可能很多读者朋友恐怕又要骂我了&#xff0c;985这个特殊的字眼也确实异常晃眼&#xff0c;实际上现在985&#xff0c;211也越来越多&#xff0c;它能代表你能够进入到更高的平台&#xff0c;拿到“高级工厂”的入场券&#xff0c;但并不意味着你会成…

每天一道算法练习题--Day14 第一章 --算法专题 --- -----------大话搜索

大话搜索 搜索一般指在有限的状态空间中进行枚举&#xff0c;通过穷尽所有的可能来找到符合条件的解或者解的个数。根据搜索方式的不同&#xff0c;搜索算法可以分为 DFS&#xff0c;BFS&#xff0c;A*算法等。这里只介绍 DFS 和 BFS&#xff0c;以及发生在 DFS 上一种技巧-回…

详解八大排序算法-附动图和源码(插入,希尔,选择,堆排序,冒泡,快速,归并,计数)

目录 &#x1f34f;一.排序的概念及应用&#x1f34f; 1.排序的概念 2.排序的应用 3.常用的排序算法 &#x1f34e;二.排序算法的实现&#x1f34e; 1.插入排序 1.1直接插入排序 1.2希尔排序&#xff08;缩小增量排序&#xff09; 2.选择排序 2.1直接选择排序 2.2堆排序…

LVS负载均衡群集部署—DR直接路由

目录 一、LVS-DR模式二、LVS-DR模式的特点三、LVS-DR中的ARP问题四、LVS-DR的优点与缺点五、为什么谁知lo:0而不是ens33:0六、LVS负载均衡群集-DR模式部署1.配置nfs共享&#xff08;192.168.154.10&#xff09;2.部署第一台nginx服务&#xff08;192.168.154.11&#xff09;3.部…

常用数据可视化对比类图表大全

优秀的数据可视化从来都不是罗列数据&#xff0c;更要根据自己的数据特征&#xff0c;设计出可以被读者轻松理解的图表。 图表类型有很多&#xff0c;选择正确图表的过程可能会让人混乱。本文将为您介绍数据可视化中比较类图表&#xff0c;以完美地表示您的数据并以最有效的方…

PostgreSQL安装和开启SSL加密连接【配置双向认证】

SSL单向认证和双向认证&#xff1a; SSL单向认证&#xff1a;只有一端校验对端的证书合法性&#xff0c;通常都是客户端来校验服务器的合法性。即在一般的单向认证中&#xff0c;只要求服务器端部署了ssl证书就行&#xff0c;客户端可以无证书&#xff0c;任何用户都可以去访问…

Rasa聊天机器人控制Python Turtle

背景 为了展示Rasa聊天机器人的使用效果以及如何将Rasa应用到业务系统中(这里将Python Turtle模块作为业务系统)&#xff0c;用户将语音或者文本输入至Rasa&#xff0c;经过处理后调用Python Turtle的功能。 turtle库是Python语言中一个很流行的绘制图像的函数库&#xff0c;想…

Docker常用命令笔记

docker常用命令 1 基础命令 sudo docker version #查看docker的版本信息 sudo docker info #查看docker系统信息&#xff0c;包括镜像和容器的数量 2 镜像命令 1&#xff0e;sudo docker images #查看本地主机的所有主机镜像 #解释 **REPOSITORY **#镜像的仓库源TAG **** …

微信小程序python+nodejs+php+springboot+vue 校园餐饮点单配送系统商家 配送员

管理员的主要功能有&#xff1a; 1.管理员输入账户登陆后台 2.个人中心&#xff1a;管理员修改密码和账户信息 3.学生管理&#xff1a;对注册的学生信息进行添加&#xff0c;修改&#xff0c;删除&#xff0c;查询 4.商家管理&#xff1a;对注册的商家信息进行添加&#xff0c;…

【在线研讨会】智慧汽车时代来临 -车规功能安全软硬件一次到位

随着科技的不断发展&#xff0c;智慧汽车的时代已经到来&#xff0c;在实现智慧汽车的过程中&#xff0c;车辆的功能安全、软硬件设计等方面都面临着严峻的挑战。为了确保智慧汽车的安全性和可靠性&#xff0c;在硬件设计方面&#xff0c;需要考虑到各种可能出现的故障和安全风…

日撸 Java 三百行day39

文章目录 说明day39 关键路径1.关键路径2. 代码分析 说明 闵老师的文章链接&#xff1a; 日撸 Java 三百行&#xff08;总述&#xff09;_minfanphd的博客-CSDN博客 自己也把手敲的代码放在了github上维护&#xff1a;https://github.com/fulisha-ok/sampledata day39 关键路…

PMP课堂模拟题目及解析(第1期)

1.在一个大型施工项目的规划阶段&#xff0c;出现了潜在的经济衰退迹象。之前关于经济衰退的风险被指定为低概率和高影响&#xff0c;预计持续 6-12 个月。项目开始后不久 发生了经济衰退&#xff0c;并按预期影响项目。六个月后&#xff0c;经济衰退影响的持续时间将更改为 24…

网络通信与密码相关概念流程

文章目录 前言一、明文通信二、密文通信1.对称加密2.非对称加密 三、安全信任机制1.CA(Certificate Authority) 证书授权中心2.数字证书 总结 前言 随着科技的发展&#xff0c;人们的通信都转化成电子通信&#xff0c;由于信息需要通过一个公有的网络进行传输&#xff0c;信息…

Spring IOC 源码解读

将回答以下问题&#xff1a; BeanFactory 和 ApplicationContext 之间的关系和区别。一个 Bean 是如何被注入到 IOC 容器里&#xff0c;中间经历了什么过程&#xff08;Bean 的生命周期&#xff09;。 先入为主 假设你已经有如下经验&#xff1a; 什么是 IOC。 don‘t call…

verilog手撕代码2——各种加法器介绍——真值表、表达式、电路图

文章目录 前言一、半加器二、全加器三、串行/行波进位加法器&#xff08;Ripple-Carry Adder/RCA&#xff09;四、超前进位加法器&#xff08;Lookahead Carry Adder/LCA&#xff09;五、进位保存加法器&#xff08;Carry Save Adder/CSA&#xff09; 前言 2023.4.25 一、半加…

Terraform

文章目录 简介安装简单使用案例 概念原理状态管理Backend 远程状态存储机制 配置语法Argument 参数Block 块terraform块required_providersbackend provider块: 与基础设施交互resource块: 定义基础架构data块: 数据源 表达式(Experssion)和函数(Functions)变量variable 输入变…

【Celery】任务Failure或一直超时Pending

编写背景 task进入队列后&#xff0c;部分任务出现Failure或者一直Pending,且业务代码没有报错。 运行环境 celery配置 from celery import Celery broker redis://:127.0.0.1:6379/1 backend redis://:127.0.0.1:6379/2 app Celery(brokerbroker,backendbackend,includ…

【文心一言】广告文案、演讲稿与请假条自动生成

前言 作为一名大学生而言&#xff0c;平时参加或者举办一些学校组织的活动的时候&#xff0c;总是避免不了需要准备一些演讲稿、广告宣传文案等内容&#xff0c;甚至于在疫情十分严重的这几年内&#xff0c;如何跟老师“委婉的”请假&#xff0c;也成为了我日常头疼的事情。但在…