【C++深入学习】类和对象(一)

在这里插入图片描述

欢迎来到Harper·Lee的学习笔记!
博主主页传送门:Harper·Lee博客主页!
欢迎各位大佬交流学习!


在这里插入图片描述

本篇本章正式进入C++的类和对象部分,本部分知识分为三小节。
复习:

  1. 结构体复习–内存对齐
  2. 编译和链接
  3. 函数栈桢的创建和销毁

一、面向过程与面向对象

1.1 面向过程

在之前学习的C语言是一种面向过程的语言,它关注的是求解问题的具体实现过程,一般通过函数调用逐步解决问题。就比如说我们以面向过程的方式分析淘米:
QQ截图20240713110621.png

1.2 面向对象

C++就是一种面向对象的语言,它将一个问题分成多个对象,更强调对象与对象之间的联系。在淘米煮饭这个例子中,一共有四个对象:米、水、锅、人。
整个过程中,这四个对象之间是交互完成任务的。在面向对象中,我们更强调对象之间的连续,并不太在意其内在是如何完成的。
QQ截图20240713110653.png

二、类的定义(class/struct)

2.1 类定义格式

  1. class是定义类的关键字,Stack是类的名称,{ }中是类的主体,注意类定义结束时后面的分号不能省略。类中的内容叫做类的成员,包括:类的属性或成员变量;类中的函数称为类的方法或成员函数。C语言中的结构体是类和函数分离的,但是C++不是。
#include<iostream>
using namespace std;
class className//类的定义方式1——class
{//成员函数void Push(int x);void Pop();int Top();//成员变量int* a;//数组int top;int capacity;
};
  1. C++将C语言中的结构体升级为类。C语言中结构体只能定义变量,在C++中,类不仅可以定义变量,还可以定义函数。
    | struct 在C/C++中的用法不同点 | C语言 | C++ |
    | — | — | — |
    |
    1. 可以定义的内容
    | struct 只能定义变量 | struct可以定义变量、函数 |
    |
    2. 类型
    | struct +结构体名 | 类名 |
    |
    3. 定义变量的方法
    | struct +结构体名才可以定义变量 | 直接类名即可定义,不需要struct 关键字,也可以写(旧法) |
    |
    4. typedef
    | 通常用typedef使类型名称简单些 | 直接类名就可以用 |
    |
    5. 能否定义类
    | C语言中struct 可以定义类 | C++中struct 可以定义类 |
//test.c
//在C语言中,一般都会使用typedef
struct Node1//结构体
{struct Node1* next;//注意这里:struct Node1*才是类型名,才能用它定义变量nextint val;
};//test.cpp
#include<iostream>
using namespace std;
struct Node2//类的定义方式2——struct
{Node2* next;//区别改变在这里,直接用类名,int val;void top();
};//这一中在C语言中是不能通过的!!!!C++兼容C语言,C语言不兼容C++!!!
int main()
{//test.cppNode2 n1;//定义n1struct Node2 n2;//定义n2,C语言的用法C++也支持!return 0;
}
  1. 定义在类里面的函数默认为 inline 内联的。

也可以进行声明和定义的分离(比如声明和定义在不同文件中)
**a. 声明和定义没有分离。**注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理

//1. 声明和定义没有分离:
#include<iostream>
using namespace std;
class Date
{
public:void Init(int year, int month, int day){_year = year;month = month;day = day;}private:int _year;int _month;int _day;
};

b.声明和定义分离。声明放在头文件(.h)中,定义放在源文件(.cpp)中。 声明和定义分离需要指定类域,就使用了::域作用限定符。
QQ截图20240713110724.png

//test.h
#include<iostream>
using namespace std;
class Date
{
public:void Init(int year, int month, int day);//声明
private:int year;int month;int day;
};//test.cpp
void Date::Init(int year, int month, int day)//定义//声明和定义分离需要指定类域,就使用了域作用限定符
{			                                 //Init是类Date的成员函数,只是声明和定义分离了而已year = year;month = month;day = day;
}

2.2 类的访问限定符

在C++中有三种访问限定符:public、private、protected
QQ截图20240713110744.png

  1. public修饰的成语言在类外可以直接被访问;
  2. protected和private修饰的成员在类外不能直接被访问;
  3. 访问权限作用域从该访问限定符出现的位置开始一直到下一个访问限定符出现为止,如果后面没有访问限定符,作用域就到 } 即类结束;
  4. class的默认访问限定符是private,struct的默认访问限定符是public。(因为struct要兼容C)
  5. ⼀般成员变量都会被限制为private/protected,需要给别人使用的成员函数会放为public。protected一般在继承中比较常用。
#include<iostream>
using namespace std;
class Date
{
public://可以访问void Init(int year, int month, int day)//非成员变量{_year = year;_month = month;_day = day;}
private://不可以访问int _year;//成员变量int _month;int _day;
};

2.3 成员变量与非成员变量的区分

从下面的代码可以看出,类中的成员变量和非成员变量之间存在着重名冲突。

#include<iostream>
using namespace std;
class Date
{
public:void Init(int year, int month, int day)//非成员变量{year = year;month = month;day = day;}
private:int year;//成员变量int month;int day;
};

C++标准并没有规定成员变量的命名规则。为了区分出成员变量,惯例上,我们在定义成员变量时会对其进行特定地修饰,比如_变量名或者是m_变量名或者变量名_。 不同公司可能都有一套自己的命名规则,但目的只是为了区分出成员变量。

#include<iostream>
using namespace std;
class Date
{
public:void Init(int year, int month, int day)//非成员变量{_year = year;_month = month;_day = day;}
private:int _year;//成员变量int _month;int _day;
};

2.4 变量声明和定义的区别

  1. 变量的声明:告知变量的名称、类型,没有开辟空间;

  2. 变量的定义:开辟了空间。如果是定义,就有空间,就可以直接使用/访问。如下面main函数中的_year。

#include<iostream>
using namespace std;
class Date
{
public:void Init(int year, int month, int day);//声明
private:int _year;//是定义还是声明????————声明int _month;int _day;
};//test.cpp
void Date::Init(int year, int month, int day)//定义
{			                              _year = year;_month = month;_day = day;
}
int main()
{Date::_year = 2024;//error,所以不能直接使用变量,说明没有开辟空间,_year是声明return 0;
}

三、类的作用域

3.1 类域的基本特点

  1. 同一个域里面不能定义同名变量,但是不同的域里面可以定义重名变量。
  2. 类域和命名空间域只影响名字隔离,不影响各自的生命周期
  3. 类域影响的是编译的查找规则, 查找默认在局部和空间去找,不会在命名空间域中去查找,除非使用== ::限定符 ==指定了类域。

3.2 编译器的查找规则

  1. (图源于博主:vpurple__)

屏幕截图 2024-07-04 172820.png


屏幕截.png

四、类对象模型

4.1 类对象的实例化

类:是对对象进行描述的、就像模型一样的东西。
类限定了类有哪些成员,类中的成员变量是一种声明,并没有分配实际的内存空间来存储它。就比如我们可以根据一张图纸(没有实际空间),创建出好几座不一样的房屋(有实际空间)。二者不一样的房子就是类实例化出的对象。
QQ截图20240713110821.png
用类名定义对象的方式,称为类的实例化。单独的类并不占据实际空间。而且一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类的成员变量。

#include<iostream>
using namespace std;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()
{//实例化出d1,d2两个对象Date d1;//Date类名就是一个类型,直接用来定义Date d2;d1.Init(2024, 7, 10);/d1.Print();d2.Init(2024, 1, 1);d2.Print();return 0;
}

4.2 类对象的存储

4.2.1 成员变量和成员函数的存储???

#include<iostream>
using namespace std;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;Date d2;d1.Init(2024, 7, 10);//使用 . 操作符访问成员对象d1.Print();d2.Init(2024, 1, 1);d2.Print();return 0;
}

上面的代码,透过汇编观察可以发现,类定义的不同对象虽然成员变量不同,就需要各自存储他们;但是调用的成员函数其实是一样的(地址是一样的),如果在每个对象里面都存储一份,就会有空间的重复浪费。(例如:用类实例化出100个对象,每个成员函数都要重复地存储100次,实属浪费!)
QQ截图20240713110850.png
其实,函数指针是不需要存储的。函数指针是一个地址,调用函数被汇编成汇编指令[call地址、jmp指令]。编译器在编译链接时就要找到函数的地址,不是在运行时找;而动态多态是在运行时找的,就需要存储函数地址。——跳转到下面的this指针
总结:

  1. 类定义出的不同对象是各自存储成员变量的。
  2. 通过汇编发现,成员函数是在编译链接时找到函数地址,函数地址存储在一个公共的地方,然后编译成汇编指令[如call地址、jmp指令等]的。
  3. 对象中只存储成员变量,而且函数体中并没有关于不同对象的区分,那么不同对象在调用成员函数Init、Print时,该函数是如何知道应该设置d1对象,而不是设置d2对象呢?——这里就引出了this指针!!!(先跳转学习this指针!)

4.3 类对象的大小

4.3.1 一般类的计算

image.pngimage.png
C++的内存对齐规则和C语言结构体中的内存对齐规则一模一样!
· 第一个成员在与结构体偏移量为0的地址处;
· 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处;
· 注意:对齐数=编译器默认的一个对齐数与该成员大小的较小值;
· VS中默认的对齐数为8;
· 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍;
• 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小;
·就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍;
C语言:自定义类型——结构体(✿༺小陈在拼命༻✿)(这一部分知识可以参考这位优秀博主)
计算A实例化对象的大小:

#include<iostream>
using namespace std;
class A
{
public:void Print(){cout << _ch << endl;}
private:char _ch;int _i;
};
int main()
{A a;cout << sizeof(a) << endl;cout << &a << endl;return 0;
}

运行结果:
image.png
画图分析:
QQ截图20240713110919.png

Q:为什么要内存对齐?
A:CPU读取内存数据时,并不是从任意位置开始读取的,读取与CPU的字长、数据总线有关,
如果CPU可以从任一位置读取,那么内存对齐规则不仅麻烦,还浪费时间。为什么还要有对齐规则呢?
读取数据与数据总线有关,32根数据总线(4Byte,数据总线数量与机器型号有关)----计算机组成原理。规定:从起始点开始,不管数据有多少,CPU一次都读取32个数据,但是这里面也许只有1个数据是CPU真正想读取的。
综合来看,内存对齐规则减少访问次数、提高了CPU的效率。

4.3.2 空类的计算

空类:类中只有成员函数或者什么也没有时,这个类就叫做空类。

//计算⼀下B/C实例化的对象是多⼤?
#include<iostream>
using namespace std;
class B
{
public:void Print(){//...}
};
class C
{};
int main()
{B b;C c;cout << sizeof(b) << endl;cout << &b << endl;cout << sizeof(c) << endl;cout << &c << endl;return 0;
}

运行结果:
image.png
B和C都是空类。首先类对象的大小不能为0,否则不能表示该对象存在过,而且还要通过B对象开空间去实例化呢。因此,C++给空类1Byte的空间用来占位标记这个类的对象的存在,实际操作中的使用性也很少。

五、this指针

5.1 this指针的引入

先观察这段代码:

#include<iostream>
using namespace std;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;Date d2;d1.Init(2024, 7, 10);//使用 . 操作符访问成员对象d1.Print();d2.Init(2024, 1, 1);d2.Print();return 0;
}

运行结果:
image.png
根据前面 3.2.1 的分析可知,类中的成员函数并没有存储在类的对象中,而且函数体中并没有关于不同对象的区分,那么函数是如何知晓自己应该访问哪个对象的呢?
C++中通过引入this指针解决该问题,即:C++编译器给每个“非静态的成员函数”增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象)(因此,this指针是一个当前类类型的指针,传参就要传入&类名定义的对象名,如 &d1)。
在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。这个隐藏的指针参数就是this指针。
类的成员函数中访问成员变量,本质都是通过this指针来访问的(编译时编译器自动会处理)。如Init函数中给_year 赋值:this -> _year = year;
加入this指针后的原型代码如下面的注释:

#include<iostream>
using namespace std;
class Date
{
public://原型:void Init(Date* const this, int year, int month, int day)void Init(int year, int month, int day){_year = year;_month = month;_day = day;}//原型:void Print(Date* const this)//const修饰的是thisvoid Print(){cout << _year << "-" << _month << "-" << _day << endl;//原型可以显示写:cout << this -> _year << "-" <<  this -> _month << "-" << this -> _day << endl;}
private:int _year;int _month;int _day;//this->_year = year;原型//this->_month = month;//this->_day = day;//这个this->可以显示地写出来,因为调用函数体中的this指针
};
int main()
{Date d1;Date d2;d1.Init(2024, 7, 10);//原型:d1.Init(&d1, 2024, 7, 10);d1.Print();			 //原型:d1.Print(&d1);d2.Init(2024, 1, 1); //原型:d2.Init(&d2,2024,1,1);d2.Print();			 //原型:d2.Print(&d2);return 0;
}

5.2 this指针的特点

  1. this指针的类型:this指针是一个当前类类型的指针, const ,所以成员函数中,不能给this指针赋值,不能修改this,可以修改this指针指向的内容的;*
  2. this指针本质上是成员函数第一个隐含的指针形参(所以this指针存储在函数栈桢中),当对象调用成员函数时,将对象地址作为实参传递给this形参,所以对象中不存储this指针;(之前计算对象实例化大小的时候都没有计算this指针的大小)
  3. this指针是指针形参,一般情况下都由编译器通过ecx寄存器自动传递,不需要用户和传递;(VS编译器)

image.png

  1. C++规定不能在实参和形参的位置显示的写this指针(编译时编译器会处理),但是可以在函数体内显示使用this指针。(如上面的代码例子)

5.3 Question

5.3.1 Q1

  1. 下面程序编译运行结果是(C.)
  • A.编译报错
  • B. 运行崩溃
  • C. 正常运行
#include<iostream>
using namespace std;
class A
{
public:void Print(){//cout << this << endl;//输出空指针0000000,不会报错,因为没有使用!!cout << "A::Print()" << endl;}
private:int _a;
};
int main()
{A* p = nullptr;//p是一个nullptr指针空值,类型为 A* ,是类类型//mov ecx pp->Print();//call 地址//p->Print(p);//这里不需要取地址!!!//p -> _a = 1;//error这个才是空指针解引用,_a存储在对象里面的(_a是public时)return 0;
}

运行结果:image.pngimage.png???
image.png
**程序正常运行,**分析过程:

  1. 编译器被编译后,底层都是将其转换成汇编指令。p->Print(); 转化的底层汇编是 call 地址,因为成员函数的地址指针不存储在对象里,该地址不在 p 对象里,编译成汇编指令后在符号表里面。
  2. 调用函数需要传递参数,参数传递 this 指针,this是类类型的一个指针,这里不需要取地址,因为 p (实参,它已经是地址了,不用取地址!)就是类类型指针,传递给行参,但是并没有使用该空指针,因此没有空指针报错!p->Print(); 并不是空指针解引用!!
  3. 成员函数并不存放在类对象中,而是存放在公共代码段。虽然我们表面看上去解引用,但实际上编译器不需要通过解引用去找对应函数,只需要去公共代码区执行对应函数即可。因此并不是空指针解引用!

5.3.2 Q2

  1. 下面程序编译运行结果是(B.)
  • A.编译报错
  • B. 运行崩溃
  • C. 正常运行
#include<iostream>
using namespace std;
class A
{
public:void Print(){cout << "A::Print()" << endl;cout << _a << endl;//这里的_a是通过this指针解引用访问的,空指针解引用!!!! }
private:int _a;
};
int main()
{A* p = nullptr;p->Print();//p->_a  = 1;//error,这里就是在类外面访问的,本来是被限制了的return 0;
}

运行结果:
image.png
程序运行崩,过程分析:
访问对应的成员变量,会传递对应对象的地址。而这里的地址为nullptr,通过nullptr->_a引起程序崩溃。

六、 C++和C语言实现Stack对比

6.1 封装

面向对象有三大特性:封装、继承、多态。
封装的概念: 用类将对象的属性(数据)与操作数据的方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
封装本质上是一种管理,让用户更方便使用类。 比如:对于电脑这样一个复杂的设备,提供给用户的就只有开关机键、通过键盘输入,显示器,USB插孔等,让用户和计算机进行交互,完成日常事务。但实际上电脑真正工作的却是CPU、显卡、内存等一些硬件元件。
类也是一样,我们使用类将数据和方法都封装起来。不想对外开放的就用 protected/private 封装起来,用 public 封装的成员允许外界对其进行合理的访问。 所以封装本质上是一种管理。

6.2 C语言实现Stack

//Stack.c
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>
typedef int STDataType;
typedef struct Stack
{STDataType* a;int top;int capacity;
}ST;
void STInit(ST* ps)
{assert(ps);ps->a = NULL;ps->top = 0;ps->capacity = 0;
}
void STDestroy(ST* ps)
{assert(ps);free(ps->a);ps->a = NULL;ps->top = ps->capacity = 0;
}
void STPush(ST* ps, STDataType x)
{assert(ps);// 满了, 扩容if (ps->top == ps->capacity){int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;STDataType* tmp = (STDataType*)realloc(ps->a, newcapacity *sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}ps->a = tmp;ps->capacity = newcapacity;}ps->a[ps->top] = x;ps->top++;
}
bool STEmpty(ST* ps)
{assert(ps);return ps->top == 0;
}
void STPop(ST* ps)
{assert(ps);assert(!STEmpty(ps));ps->top--;
}
STDataType STTop(ST* ps)
{assert(ps);assert(!STEmpty(ps));return ps->a[ps->top - 1];
}
int STSize(ST* ps)
{assert(ps);return ps->top;
}
int main()
{ST s;STInit(&s);STPush(&s, 1);STPush(&s, 2);STPush(&s, 3);STPush(&s, 4);while (!STEmpty(&s)){printf("%d\n", STTop(&s));STPop(&s);}STDestroy(&s);//s.a[s.top]可以直接访问栈顶元素,但是不规范//但是这种访问方式并不好,万一栈是空栈时,越界!//所以用C语言这样的实现不怎么规范,而且存在风险!!!return 0;
}

6.3 C++实现Stack

//Stcak.cpp
#include<iostream>
using namespace std;
typedef int STDataType;
class Stack
{
public:// 成员函数void Init(int n = 4){_a = (STDataType*)malloc(sizeof(STDataType) * n);if (nullptr == _a){perror("malloc申请空间失败");return;}_capacity = n;_top = 0;}void Push(STDataType x){if (_top == _capacity){int newcapacity = _capacity * 2;STDataType* tmp = (STDataType*)realloc(_a, newcapacity *sizeof(STDataType));if (tmp == NULL){perror("realloc fail");return;}_a = tmp;_capacity = newcapacity;}_a[_top++] = x;}void Pop(){assert(_top > 0);--_top;}bool Empty(){return _top == 0;}int Top(){assert(_top > 0);return _a[_top - 1];}void Destroy(){free(_a);_a = nullptr;_top = _capacity = 0;}
private:// 成员变量STDataType * _a;size_t _capacity;size_t _top;
};
int main()
{Stack s;s.Init();s.Push(1);s.Push(2);s.Push(3);s.Push(4);while (!s.Empty()){printf("%d\n", s.Top());s.Pop();}s.Destroy();return 0;
}

C++中数据和函数都放到了类里面,通过访问限定符进性了限制,不能再随意通过对象直接修改数据,这是C++封装的⼀种体现,这个是最重要的变化。这里的封装的本质是一种更严格规范的管理,避免出现乱访问修改的问题。
想想我们是如何管理陕西省的兵马俑的。我们若什么都不管,兵马俑就被随意破坏了。所以我们建立了一座房子将兵马俑封装起来。但是我们封装的目的不是为了不给别人看,所以我们开放了售票通道,人们可以通过买票突破封装,在合理的监管机制下进去参观。

在这里插入图片描述
创作不易,喜欢的uu记得三连支持一下哦!
在这里插入图片描述
在这里插入图片描述

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

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

相关文章

再升级!视频理解大模型 CogVLM2 开源

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对大模型技术趋势、算法项目落地经验分享、新手如何入门算法岗、该如何准备面试攻略、面试常考点等热门话题进行了深入的讨论。 总结链接如…

基于JAVA-JSP的电子书下载系统设计与实现

点击下载源码 基于JAVA-JSP电子书下载系统 目 录 第1章 绪论 1 课题的研究背景、内容和意义 1 第2章 主要技术概述 3 2.1 B/S结构 3 2.2 JSP技术 4 2.2.1 JSP技术的强势 5 2.2.2 JSP技术的弱势 5 2.3 SQL SERVER 2000数据库 5 2.4 JDBC数据库连接 6 2.4.1 JDBC接口 …

Mathematica笔记

Mathematica笔记 mathematica等距、不等距数组mathematica多条线作图与循环图例 mathematica等距、不等距数组 mathematica多条线作图与循环图例 Clear["*"] h[x_, a_] a*E^x; LogLogPlot[Evaluate[Table[h[x, i], {i, 1, 20, 2}]], {x, 0.001, 10}, PlotRange -&g…

OpenGL笔记八之EBO和EBO绘制流程

OpenGL笔记八之EBO和EBO绘制流程 —— 2024-07-07 晚上 总结自bilibili赵新政老师的教程 code review! 文章目录 OpenGL笔记八之EBO和EBO绘制流程1.EBO2.glDrawElements&#xff1a;如果使用了ebo&#xff0c;最后一个参数可以写03.glDrawElements&#xff1a;如果使用了ebo…

CSS技巧专栏:一日一例 2.纯CSS实现 多彩边框按钮特效

大家好,今天是 CSS技巧一日一例 专栏的第二篇《纯CSS实现多彩边框按钮特效》 先看图: 开工前的准备工作 正如昨日所讲,为了案例的表现,也处于书写的习惯,在今天的案例开工前,先把昨天的准备工作重做一遍。 清除浏览器的默认样式定义页面基本颜色设定body的样式清除butt…

2024辽宁省数学建模B题【钢铁产品质量优化】思路详解

2024 辽宁省大学数学建模竞赛试题 B 题 钢铁产品质量优化 由于连续退火工序中各阶段的工艺参数之间存在耦合性&#xff08;加热炉的温度设定会影响后续均热与冷却温度的设定&#xff0c;以及带钢穿行速度&#xff09;&#xff0c;导致难以建立该工序的机理模型&#xff0c;从而…

科特勒营销管理学读后感01

营销管理学之名词解释 任务环境可以理解为营销平台规模&#xff0c;公司营销渠道等等&#xff0c;宏观环境则是社会状况&#xff0c;环境状况。&#xff08;个人理解&#xff09;

js逆向-webpack-python

网站&#xff08;base64&#xff09;&#xff1a;aHR0cHM6Ly93d3cuY29pbmdsYXNzLmNvbS96aA 案例响应解密爬取&#xff08;webpack&#xff09; 1、找到目标url 2、进行入口定位&#xff08;此案例使用 ‘decrypt(’ 关键字搜索 &#xff09; 3、找到位置进行分析 --t 为 dat…

【Redis】初识 Redis

文章目录 1 什么是 Redis2 Redis 的特点2.1 速度快2.2 可编程性2.3 可拓展性2.4 持久化2.5 主从复制2.5 高可用和分布式2.6 客户端语言多 3 Redis 使用场景3.1 实时数据存储3.2 缓存和 Session 存储3.3 消息队列 4 Redis 重大版本5 CentOS7 安装 Redis5 1 什么是 Redis Redis …

CSS实现超链接标签:鼠标光标为手形、取消下划线、当鼠标悬停时显示下划线

1、鼠标光标为手形 cursor: pointer; 2、显示/取消下划线 text-decoration: none; /* 文本取消下划线 */ text-decoration: underline; /* 文本添加下划线 */ 3、伪类选择器 伪类选择器是 CSS 中已经定义好的选择器&#xff0c;因此程序员不能随意命令。伪类选择器…

JVM系列 | 垃圾收集算法

JVM系列 | 垃圾收集算法 文章目录 前言如何判断对象已"死"&#xff1f;引用计数法可达性分析算法可达性分析2.0版 | 引用的增强对象的消亡过程回收方法区主要回收目标&#xff1a;回收操作 垃圾收集算法分代收集理论 与 跨代引用假说分代收集理论跨带引用假说 垃圾收…

《GroupViT: Semantic Segmentation Emerges from Text Supervision》论文解读

会议&#xff1a;CVPR 年份&#xff1a;2022 代码&#xff1a;https://github.com/NVlabs/GroupViT 研究背景与动机&#xff1a; 传统深度学习系统中&#xff0c;图像区域的Grouping通常是隐式通过像素级识别标签的自上而下监督来实现的。作者提出将Grouping机制重新引入深…

LeetCode热题100刷题12:20. 有效的括号、394. 字符串解码、739. 每日温度、155. 最小栈、139. 单词拆分

20. 有效的括号 class Solution { public:bool isValid(string s) {if(s.size()%2 !0)return false;stack<char> st;for(int i0;i<s.size();i) {if(s[i]( || s[i]{ || s[i][)st.push(s[i]);else if(st.empty() && (s[i]} || s[i]] || s[i])))return false;els…

MySQL 数据库(基础)- 约束

MySQL 数据库&#xff08;基础&#xff09;- 约束 概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。目的&#xff1a;保证数据库中数据的正确&#xff0c;有效性和完成性。分类&#xff1a; 注意&#xff1a;约束是作用在表中字段上的&am…

yoloV8导出engine模型

yoloV8导出engine模型 引言&#xff1a; 目的是TensorRT加速YOLO实例分割模型。 本博客记录达成此目的所需的步骤&#xff0c;及步骤中可能遇到的问题。 as follow&#xff1a; 1. 首先导出onnx模型的脚本命令&#xff1a; yolo export modelbest.pt formatonnx opset12 simpl…

[misc]-流量包-find the pass

提示&#xff1a;黑客抓到一段流量&#xff0c;找找管理员的密码是多少 直接追踪流发现pass flag ffb7567a1d4f4abdffdb54e022f8facd

【RNN练习】天气预测

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 一、环境及数据准备 1. 我的环境 语言环境&#xff1a;Python3.11.9编译器&#xff1a;Jupyter notebook深度学习框架&#xff1a;TensorFlow 2.15.0 2. 导…

2024的开放式耳机排行榜,看这六个耳机选购的小Tips

在选择适合散步聊天和听歌的耳机时&#xff0c;开放式耳机是一个很好的选择。相对于传统的入耳式耳机&#xff0c;开放式耳机不会过度隔离你与周围环境&#xff0c;这意味着你可以更自然地与朋友交流&#xff0c;并且更加安全地行走在路上。市面上有许多开放式耳机可供选择&…

01. Hibernate 教程简介

1. 前言 大家好&#xff01;本节课将和大家一起学习鼎鼎有名的 Hibernate 框架。 本节课程将向大家介绍&#xff1a; Hibernate 的功能 、特点&#xff1b;Hibernate 产生的背景&#xff1b;并初步探讨编写 Jdbc 框架的基础构建思路。 2. Hibernate 是什么&#xff1f; 简而…

尚硅谷js

原型模式 原型对象就是相当于java的static,所有实例对象可以直接用静态的属性或者方法 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script type"text/javascript&q…