当前位置: 首页 > news >正文

C++初识类和对象

前言

上一期我们介绍了一些C++入门的基础知识,本期我们来介绍面向对象。初步认识一下面向对象和面向过程、类、以及封装!

本期内容介绍

面向过程和面向对象

类的引入

类的定义

类的访问限定符和封装

类的作用域

类的实例化

类对象模型

this指针

一、面向过程和面向对象

面向过程(C语言)关注的是过程,即分析出求解问题的步骤,通过函数调用逐步解决问题。而面向对象(C++)关注的是对象,即解决的事情被分成不同的对象,各个对象配合完成

以前我也不怎么理解面向对象和面向过程!后来看到了很多例子后逐渐有了理解!我来举一个我以前理解最好的例子 --- 洗衣服。

面向过程:用面向过程来洗衣服的步骤:找盆 ---> 接水 ---> 放洗衣液 ---> 放衣服 ---> 手搓 ---> 换水 ---> 再洗 ---> 换水 ---> 拧干 ---> 晾晒。你得关注每一步的过程

面想对象:用面向对象来洗衣服的步骤:人、衣服、洗衣机、洗衣液。整个过程就是人将衣服洗衣液,放到洗衣机中启动洗衣机,洗衣机洗好了会烘干!具体的洗衣服和烘干过程你根本不用关心,这是洗衣机的事情!

当然还有其他同类的例子,例如把大象装到冰箱里面!

二、类的引入

C语言的struct只能定义变量,在C++中不仅可以定义变量,而且可以定义函数。例如我们以前C语言中玩的栈,就是只能在结构中定义变量,而C++中可以定义函数!

C语言版本:

typedef int STDataType;
struct Stack
{STDataType* a;int top;int capacity;
};

他的方法只能在外面!而C++就可以在里面!

C++版本:

#include <iostream>typedef int STDataType;
struct Stack
{STDataType* _a;int _top;int _capacity;void Init(int capacity = 4){_a = (STDataType*)malloc(sizeof(STDataType) * capacity);if (_a == nullptr){perror("malloc failed");exit(-1);}_capacity = capacity;_top = 0;}//...
};

上述操作可以,但C++中更喜欢用class来替代struct

三、类的定义

class ClassName
{//成员变量和成员方法(函数)
};//注意封号

class是C++中定义类的关键字ClassName 是类的名字 {}中为是类的主体。和struct一样结束的 ; 不能省略

类体中(即{}中)的内容被称为类的成员,成员被分为变量和函数。成员变量又被称为成员的属性,用来描述该对象的特征成员函数又被成为成员方法,是描述类的行为的!

类的两种定义方式

1、声明和定义全部放在类体中,需要注意的是:成员函数在类体中默认是内联的!

class Student
{
public://成员方法void sleep(){cout << _name << "正在sleep()..." << endl;}private://成员属性char* _name;char* _sex;int _age;
};

当然这里用struct也可以定义类!

2、声明和定义分开即声明放在.h,定义在.cpp中时,在定义的成员函数名前需要加类名和作用域限定符::,来指定是哪个域的!

小tips: 我们一般建议使用第二种

成员变量的命名规则

我一般习惯时在成员属性的成员的前面加一个下划线,这个的作用主要是区分形参和成员属性的。具体怎么加,看你的想法,以及需求,只要能分开都可以!但也要符合我们以前C语言介绍过的标识符命名规则!如下就是C语言的表示符命名规则:

  1. 标识符只能由字母、数字和下划线组成。
  2. 标识符必须以字母或下划线开头,不能以数字开头。
  3. 标识符区分大小写。
  4. 标识符的长度没有限制,但只有前31个字符有效。
  5. C语言的关键字(如if、for、while等)不能用作标识符。
  6. 标识符不能包含空格或其他特殊字符(如@、#、$等)。
  7. 一般情况下,标识符应具有描述性和易于理解的名称。

四、类的访问限定符和封装

访问限定符

C++中访问限定符有三个,分别是:public(公有的)protected(被保护的)private(私有的)

访问限定符的说明

public修饰的成员在类外可以直接访问

protec和private修饰的成员再类外面不能直接访问(目前认为他两一样,到后面介绍了继承、多态再解释他两的区别)

访问权限的作用域该访问限定符开始到下一个访问限定符结束, 如果没有出现下一个访问限定符,则到}终止

class的默认访问权限是private的,struct为public的(因为struct要兼容C语言)

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

OK, 举个栗子看看:

public(在类外可以访问,以属性举例,方法同理):

class Stack
{
public:void Init(int capacity = 3){_a = (int*)malloc(sizeof(int) * capacity);if (_a == nullptr){perror("malloc failed");exit(-1);}_size = 0;_capacity = capacity;}void Push(int x){//...}int* _a;int _size;int _capacity;
};int main()
{Stack s;s.Init();cout << s._size << endl;return 0;
}

这里把class直接换成struct也可以!

private/protectedd当前认为是一样的,在类外不可访问:

C++中struct和class的区别是什么?

C++需要兼容C语言,所以C++中的struct可以当成结构体使用。另外C++中的struct还可以和class一样用来定义类。区别是struct定义类的访问权限是public,class定义的类的访问权限是private。另外在继承和模板参数列表位置也是与区别的(后期介绍了会在拿出来介绍的)!

注意:在C++中如果用struct定义结构体的话,在结构体类在申明结构体变量时,不用在+struct了

struct SLNode
{int* data;SLNode* next;
};

原因是:C++对struct进行了升级变成了类,用它定义的就是一个类型,所以就可以直接用,C语言是struct _name{}才是一个类型!

封装

理论层面:C++实现封装的方式:用类将对象的属性和方法结合到一块,让对象更加完善,通过访问权限来隐藏内部具体的实现细节选择性的把其部分接口提供给外部调用者(用户)。

代码层面:在C++类的内部,把不想让类外部直接访问的成员用private修饰,外部要访问只能使用提供公开的接口!

封装的本质是一种管理,为了让用户使用起来方便!

OK,来举一个栗子。你现在看这篇博客的手机或电脑,它的组成较为复杂,他只给用户提供开机键,输入输出设备即键盘显示器等让用户和计算机能进行交互的接口,但他真正工作的是CPU显卡等硬件!但你用关心这些吗?是不是不用啊!你只需要在人家给你的提供的接口上操作即可,管他的谁工作、如何工作。只要能完成你的操作即可~!

五、类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类外面定义时,需要使用::作用域限定符来指定成员属于哪个类!

class Date
{
public:void Init(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print();private:int _year;int _month;int _day;
};//这里注意要指定Print属于Date这个类
void Date::Print()
{cout << "999" << endl;
}

六、类的实例化

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

//类
class Date
{
public:void Init(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}private:int _year;int _month;int _day;
};int main()
{Date d;//实例化一个对象d.Init(2023, 11, 25);d.Print();return 0;
}

1、类是描述对象的,是一个模型(模板),它限制了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储他。例如:开学时填写的学生信息表,这个表可以看成一个学生类,他来描述具体的学生(对象)!

2、一个类可以实例化多个对象,实例化出来的对象占用实际的物理空间,存储类成员变量

例如:刚刚上面说的把学生开学的信息表看做一个学生类的话,每登记一个学生就实例化了一个对象,而这个表可以被很多学生填写(实例化多个对象)!每个实例化出来的学生对象才有自己的实际空间(例如宿舍),这些学生有属于自己的年龄、姓名、性别等成员属性!

或者:你可以把盖楼房的图纸理解成一个类,按照这个图纸可以修很多的房子(实例化多个对象),图纸本身不占实际的空间,真正占空间的是按照图纸盖的房子,这些实例化的房子有客厅、卧室等属性!

七、类对象模型

上面我们已经清楚了类的定义以及其实例化对象。一个对象有成员属性也有成员的方法,而我们想知道的是一个对象包含了什么?

OK,关于这个问题我就直接先说结论,再解释了:

一个对象包含了成员属性和成员方法。成员属性是对象自身的属性(成员变量),也就是说成员属性属于对象。而成员方法是这个类都有的行为是属于类(所有类的对象都有成员)。

我用一个我家鸽鸽的例子来说明:我家鸽鸽属于人这个类,他的名字和性别等是他个人独属于的!他的成员方法(行为)有:唱、条、rap、打篮球。但只有我家鸽鸽会唱、条、rap、打篮球吗?你是不是也可以啊,所以类的成员方法属于类!

class People
{
public://方法属于整个类void Sing(){cout << "鸡你太美~..." << endl;}private://属性属于对象本身char _name[20];char _sex[5];int age;
};

如何计算一个类的大小?

可以用sizeof这个操作符来计算类的大小!一个类的大小是该类中的成员变量之和(不包含静态成员变量,虽然静态成员变量属于类但对类的大小无影响),当然要注意内存对齐!如果是没有成员变量的类,编译器会给一个字节来唯一标识这个类

//既有成员变量又有成员方法的类
class A
{
public:void Print(){//...}private:int a;
};//只有成员方法没有成员变量的类
class B
{
public:void Print(){//...}
};//既没有成员变量有没有成员方法的类(空类)
class C
{};int main()
{cout << sizeof(A) << endl;cout << sizeof(B) << endl;cout << sizeof(C) << endl;return 0;
}

目前我们可以认为类的大小和对象的大小是一样的!一个是在图纸上算空间,一个是实地测量!

结构体内存对齐规则(和C语言的一样)

1.结构的第一个成员变量永远放在相较于结构体起始位置偏移量为0处!

2.从第二个开始,后面的每个元素都要对齐到某个对齐数的整数倍处!对齐数:结构体成员自身大小和默认对齐数的较小值!

在VS上默认对齐数是8,而在gcc是没有默认对齐数的(对齐数就是成员的自身大小)!

3.结构体的总大小,必须是最大对齐数的整数倍。最大对齐数:所有成员的对齐数中的最大值!

4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数的整数倍(包含嵌套结构体的对齐数)!

如果这块还有问题,请点击后面的链接,这篇博文中我详细介绍过它的计算和栗子:

内存对齐

八、this指针

this指针的引出

我们先来看下面 一段代码的结果:

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, 11, 25);d1.Print();Date d2;d2.Init(2023, 11, 26);d2.Print();return 0;
}

Init和Print是类的成员方法,我们并没有指定是哪个对象的,为什么我们在调d1.Init的时候就是给d1对象赋值而不是给d2初始化呢?我们在d2.Print的时候是打印d2的属性的信息,为什么不打印d1会随机值呢????他到底是如何区别的呢?

C++为了解决上述的问题引入了this指针来解决!C++编译器给每一个静态的成员函数都增加了一个隐藏的指针参数,让这个指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有的成员变量的操作,都是通过该指针去访问的。只不过所有的操作对用户是不可见的,也不需要用户手动传,编译器会自动完成!!

this指针的特性

1、this指针的类型:类类型* const ,即此时的const修饰this,只能在形参接受被实参拷贝的时候赋值一次,在成员函数中,不能给this赋值

2、this只能在成员函数(非静态成员函数,静态的成员函数没有this后面会再解释)内部使用,可以显示的写

3、this指针本质成员函数的形参(非静态成员函数),当对象调用成员函数,将对象的地址会传给this,所以对象不存储this指针

4、this指针成员函数(非静态成员函数)第一个隐含的指针参数(形参),一般情况由寄存器ecx自动传递,调用者不需要手动传递

this指针存在哪里?this指针可以为空吗?

这应该是这里很坑的两个问题了,对基础考察很细!OK,我还是先说结论,再用栗子来解释!

this指针是形参,存储在函数栈帧上!this可以为空,但为空时不能去访问成员属性否则就是则空指针异常操作了!

OK,两个栗子分别解释一下:

栗子1:下列程序的编译运行的结果是?A、编译报错  B、运行奔溃  C、正常运行

class A
{
public:void Print(){cout << "Print()" << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}

OK,他是C、正常运行!我们来看一下:

原因是:这里虽然p是nullptr但他是个对象指针,他->Print是调用类的方法,当然没有问题!他调用Print传参的时候的确是nullpttr,this指针接收的是nullptr但他没有访问成员属性啊!所以不会报错!正常运行!

这里可能有点绕,我来举个栗子,这里的p假设是一个叫张三驴的学霸,它的分数是700,他可不可以报清华?当然可以。人家之人你的分数,不管你的人。这里也是一样,人家直看你是不是类的对象,不管你是不是nullptr 。咱们的张三驴同学虽然收到了很多学校的抢人电话并提前发了录取通知书,但他不去上,是不是就和他没有关系了。这里也是一样,我this的确是nullptr但我没用它访问成员变量呀!

栗子2:下列程序的编译运行的结果是?A、编译报错  B、运行奔溃  C、正常运行


class A
{
public:void PrintA(){cout << _a << endl;}
private:int _a;
};int main()
{A* p = nullptr;p->PrintA();return 0;
}

OK,这里是B、运行崩溃!

原因是对空指针进行了操作!和上面的不一样的是下面的Print访问了成员员变量_a,这就出问题了,this是空,指向一块不存在的内存,你咋访问!就出问题了!还是上面的例子:我们的张三驴同学不小心收到了清京大学,一激动以为是那两所顶尖高校合作的一个学校。可高兴了,结果把学费一交都查不到学校地址~.....

C语言和C++实现栈的对比

C语言

#include <assert.h>
typedef int DataType;
typedef struct Stack
{DataType* array;int capacity;int size;
}Stack;void StackInit(Stack* ps)
{assert(ps);ps->array = (DataType*)malloc(sizeof(DataType) * 3);if (NULL == ps->array){assert(0);return;}ps->capacity = 3;ps->size = 0;
}void StackDestroy(Stack* ps)
{assert(ps);if (ps->array){free(ps->array);ps->array = NULL;ps->capacity = 0;ps->size = 0;}
}void CheckCapacity(Stack* ps)
{if (ps->size == ps->capacity){int newcapacity = ps->capacity * 2;DataType* temp = (DataType*)realloc(ps->array,newcapacity * sizeof(DataType));if (temp == NULL){perror("realloc申请空间失败!!!");return;}ps->array = temp;ps->capacity = newcapacity;}
}void StackPush(Stack* ps, DataType data)
{assert(ps);CheckCapacity(ps);ps->array[ps->size] = data;ps->size++;
}int StackEmpty(Stack* ps)
{assert(ps);return 0 == ps->size;
}void StackPop(Stack* ps)
{if (StackEmpty(ps))return;ps->size--;
}DataType StackTop(Stack* ps)
{assert(!StackEmpty(ps));return ps->array[ps->size - 1];}int StackSize(Stack* ps)
{assert(ps);return ps->size;
}int main()
{Stack s;StackInit(&s);StackPush(&s, 1);StackPush(&s, 2);StackPush(&s, 3);StackPush(&s, 4);printf("%d\n", StackTop(&s));printf("%d\n", StackSize(&s));StackPop(&s);StackPop(&s);printf("%d\n", StackTop(&s));printf("%d\n", StackSize(&s));StackDestroy(&s);return 0;
}
可以看到,在用 C 语言实现时, Stack 相关操作函数有以下共性:
每个函数的第一个参数都是 Stack*
函数中必须要对第一个参数检测,因为该参数可能会为 NULL
函数中都是通过 Stack* 参数操作栈的
调用时必须传递 Stack 结构体变量的地址
结构体中只能定义存放数据的结构,操作数据的方法不能放在结构体中,即 数据和操作数据
的方式是分离开的 ,而且实现上相当复杂一点,涉及到大量指针操作,稍不注意可能就会出
错。

C++:

typedef int DataType;
class Stack
{
public:void Init(){_array = (DataType*)malloc(sizeof(DataType) * 3);if (NULL == _array){perror("malloc申请空间失败!!!");return;}_capacity = 3;_size = 0;}void Push(DataType data){CheckCapacity();_array[_size] = data;_size++;}void Pop(){if (Empty())return;_size--;}DataType Top() { return _array[_size - 1]; }int Empty() { return 0 == _size; }int Size() { return _size; }void Destroy(){if (_array){free(_array);_array = NULL;_capacity = 0;_size = 0;}}private:void CheckCapacity(){if (_size == _capacity){int newcapacity = _capacity * 2;DataType* temp = (DataType*)realloc(_array, newcapacity *sizeof(DataType));if (temp == NULL){perror("realloc申请空间失败!!!");return;}_array = temp;_capacity = newcapacity;}}private:DataType* _array;int _capacity;int _size;
};int main()
{Stack s;s.Init();s.Push(1);s.Push(2);s.Push(3);s.Push(4);printf("%d\n", s.Top());printf("%d\n", s.Size());s.Pop();s.Pop();printf("%d\n", s.Top());printf("%d\n", s.Size());s.Destroy();return 0;
}
C++ 中通过类可以将数据 以及 操作数据的方法进行完美结合,通过访问权限可以控制那些方法在 类外可以被调用,即封装 ,在使用时就像使用自己的成员一样,更符合人类对一件事物的认知。
而且每个方法不需要传递 Stack* 的参数了,编译器编译之后该参数会自动还原,即 C++ Stack * 参数是编译器维护的, C 语言中需用用户自己维护

相关文章:

C++初识类和对象

前言 上一期我们介绍了一些C入门的基础知识&#xff0c;本期我们来介绍面向对象。初步认识一下面向对象和面向过程、类、以及封装&#xff01; 本期内容介绍 面向过程和面向对象 类的引入 类的定义 类的访问限定符和封装 类的作用域 类的实例化 类对象模型 this指针 一、面向…...

MYSQL where 子句

文章目录 前言MySQL where 子句语法 从命令提示符中读取数据使用PHP脚本读取数据后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Mysql &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努力…...

系列十六、Spring IOC容器的扩展点

一、概述 Spring IOC容器的扩展点是指在IOC加载的过程中&#xff0c;如何对即将要创建的bean进行扩展。 二、扩展点 2.1、BeanDefinitionRegistryPostProcessor 2.1.1、概述 BeanDefinitionRegistryPostProcessor是bean定义的后置处理器&#xff0c;在BeanDefinition加载后&a…...

eclipse项目移到idea上部署运行

1.配置web模块 另外&#xff0c;模块这里&#xff0c;也要加上Spring 2.配置Artifact &#xff08;用于tomcat&#xff09; 就是从上面配置的web模块&#xff0c;产生的工件 3.添加lib 一般是在web-inf/lib &#xff0c; 遇到的坑&#xff1a; jdk版本问题&#xff0c;这里…...

支持向量机的算法原理

支持向量机&#xff08;Support Vector Machine&#xff0c;简称SVM&#xff09;是机器学习领域中一种常用的分类算法&#xff0c;它基于统计学习理论和结构风险最小化原则&#xff0c;具有很强的理论基础和良好的分类性能。本文将详细介绍支持向量机的算法原理&#xff0c;并解…...

gitlab 12升级14(解决各种报错问题)

1.这里是从自己公司的源下载的rpm包&#xff0c;需要换成自己的 2.从12的最后一个版本升级到14的最后一个版本 # 停服务 [rootdocker test]# gitlab-ctl stop puma && gitlab-ctl stop sidekiq && gitlab-ctl stop nginx && gitlab-ctl status# 进入…...

给element plus中动态form-item增加校验的可行方法

element plus中的form组件自带校验机制。在常规使用场景中&#xff0c;表单项是固定的、明确的&#xff0c;且数量不会太多。校验规则的使用也如下&#xff1a; <template><div class"edit-page"><el-form :model"formModel" ref"for…...

C++学习之值传递

c/c中存在三种传值方式&#xff0c;在局部函数中&#xff0c;对这三种传值方式传入的参数进行修改&#xff0c;会得到不同的结果。具体见下例&#xff1a; #include <stdlib.h> #include <stdio.h>static int dummny 10000;// 传值(传过来的是原始值的副本&#…...

网络视频播放卡顿原因分析

一、问题描述 某项目通过拉摄像机rtsp流转rtmp/http-flv/ws-flv的方案&#xff0c;使用户可以在网页中观看摄像机的视频画面。在 观看视频时偶发出现卡顿现象。 二、卡顿现象分析和解决 此问题涉及的原因较多&#xff0c;所以得考虑各环节的问题可能性&#xff0c;并根据现场实…...

Android 相机库CameraView源码解析 (二) : 拍照

1. 前言 这段时间&#xff0c;在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位&#xff0c;在项目前期&#xff0c;的确为我们节省了不少时间。 但随着项目持续深入&#xff0c;对于CameraView的使用进入深水区&#xff0c;逐…...

计算机缺少d3dx9_43.dll怎么办?5个方法快速修复d3dx9_43.dll文件

在计算机使用过程中&#xff0c;我们常常会遇到一些错误提示&#xff0c;其中之一就是“d3dx9_43.dll丢失”。这个问题可能会影响到我们的游戏体验或者软件运行。为了解决这个问题&#xff0c;我查阅了一些资料并尝试了多种方法。在这里&#xff0c;我想分享一下我对d3dx9_43.d…...

2023亚太杯数学建模C题思路分析 - 我国新能源电动汽车的发展趋势

1 赛题 问题C 我国新能源电动汽车的发展趋势 新能源汽车是指以先进技术原理、新技术、新结构的非常规汽车燃料为动力来源( 非常规汽车燃料指汽油、柴油以外的燃料&#xff09;&#xff0c;将先进技术进行汽车动力控制和驱动相结 合的汽车。新能源汽车主要包括四种类型&#x…...

c语言新龟兔赛跑

以下是一个使用C语言编写的新的龟兔赛跑游戏&#xff1a; #include <stdio.h>#include <stdlib.h>#include <time.h>int main() { int distance, turtle_speed, rabbit_speed, turtle_time, rabbit_time, rabbit_lead; srand(time(NULL)); // 随机数种…...

Linux驱动开发——网络设备驱动(理论篇)

目录 一、前言 二、网络层次结构 三、网络设备驱动核心数据结构和函数 一、前言 网络设备驱动是 Linux 的第三大类驱动&#xff0c;也是我们学习的最后一类 Linux 驱动。这里我们首先简单学习一下网络协议层次结构&#xff0c;然后简单讨论 Linux 内核中网络实现的层次结构。…...

simulink仿真

1&#xff09;系统问题 连续系统&#xff0c;离散系统&#xff08;采样周期问题&#xff09; 系统分析问题 2&#xff09;求解器问题 变步长&#xff0c;定步长&#xff0c;步长时间与采样周期问题、 3&#xff09;积分器问题 连续积分&#xff0c;离散积分问题&#xff…...

PC端页面进去先出现加载效果

自定义指令v-loading&#xff0c;只需要绑定Boolean即可 v-loading“loading” <el-table :data"list" border style"width: 100%" v-loading"loading"><el-table-column align"center" label"序号" width"5…...

磁盘清理在哪里?学会这4个方法,快速清理内存!

“在使用电脑的过程中&#xff0c;我可能经常会保存一些文件到电脑上&#xff0c;这也导致电脑经常出现内存不足的情况。我想问问磁盘清理在哪里呀&#xff1f;我应该如何打开呢&#xff1f;” 随着使用电脑的时间增长&#xff0c;用户可能经常会遇到磁盘空间不足的情况&#x…...

Error opening terminal: xterm.”的解决方法

主要是看下面这两个变量是否设置正确 $ echo $TERM $ echo $TERMINFO 通常TERM的默认值为xterm-265color, 要查看支持的term&#xff0c;可以ls -al /lib/terminfo/x/ 如果TERM是xterm-265color的话&#xff0c;TERMINFO设置为/usr/lib/terminfo make menuconfig时提示“Err…...

C#常见的设计模式-结构型模式

引言 设计模式是软件工程中用于解决常见问题的可复用解决方案。在C#编程中&#xff0c;常见的设计模式具有广泛的应用。本篇博客将重点介绍C#中常见的结构型设计模式&#xff0c;包括适配器模式、装饰器模式、代理模式、组合模式和享元模式。 目录 引言1. 适配器模式(Adapter …...

Redis分片备库切换操作

Redis分片备库切换操作 场景描述&#xff1a; 分片集群&#xff1a; 1.ipa:5001-ipa:5002 2.ipb:5001-ipb:5002 需将两个分片备库互置完成灾备 操作步骤 准备工作 主机密码&#xff1a;1qaz!QAZ 获取节点信息命令 /redispath/bin/redis-cli -a password -h ip -p port red…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

关于nvm与node.js

1 安装nvm 安装过程中手动修改 nvm的安装路径&#xff0c; 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解&#xff0c;但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后&#xff0c;通常在该文件中会出现以下配置&…...

UE5 学习系列(三)创建和移动物体

这篇博客是该系列的第三篇&#xff0c;是在之前两篇博客的基础上展开&#xff0c;主要介绍如何在操作界面中创建和拖动物体&#xff0c;这篇博客跟随的视频链接如下&#xff1a; B 站视频&#xff1a;s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...