C++初识类和对象

news2025/2/23 2:59:00

前言

上一期我们介绍了一些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 语言中需用用户自己维护

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

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

相关文章

从零开始学习管道:管道程序的优化和文件描述符继承问题

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客主要内容管道后续的完善&#xff0c;以及解决管道继承多个文件描…

Unity - Graphic解析

Gpahic 的作用 Graphic 是 Unity最基础的图形基类。主要负责UGUI的显示部分。 由上图可以看你出我们经常使用的Image&#xff0c;Text&#xff0c;都是继承自Graphic。 Graphic的渲染流程 在Graphic的源码中有以下属性 [NonSerialized] private CanvasRenderer m_CanvasRend…

【Python游戏开发】使用Python编写拼图益智游戏教程

使用Python编写拼图益智游戏 大家一般都玩过拼图益智游戏&#xff0c;或者类似的游戏。今天&#xff0c;就给大家使用pygame库在Python中构建一个拼图益智小游戏。这个拼图小游戏是构建一个围绕着将1-15个数字排列在16个方块的网格中的游戏。 现在&#xff0c;让我们从今天的惊…

【数据中台】开源项目(2)-Dbus数据总线

1 背景 企业中大量业务数据保存在各个业务系统数据库中&#xff0c;过去通常的同步数据的方法有很多种&#xff0c;比如&#xff1a; 各个数据使用方在业务低峰期各种抽取所需数据&#xff08;缺点是存在重复抽取而且数据不一致&#xff09; 由统一的数仓平台通过sqoop到各个…

那些年,关于CKACKS认证的那些事儿?

前言 遥想2020年的年初&#xff0c;疫情封城封村之际&#xff0c;工作之余在B站将尚硅谷的linux中的k8s视频完整系统的学习了一遍&#xff0c;自此像是打通了任督二脉一般&#xff0c;开启了对k8s的探索之旅&#xff0c;一路也是磕磕绊绊的在工作中使用k8s。 终于在23年的6月仲…

Rust在Web开发中的应用

欢迎关注我的公众号lincyang新自媒体&#xff0c;回复关键字【程序员经典书单】&#xff0c;领取程序员的100本经典书单 大家好&#xff01;我是lincyang。 今天我们将一起深入探索Rust在Web开发领域的应用。尽管Rust最初设计用于系统编程&#xff0c;但其性能、安全性和现代并…

CANdelaStudio 使用教程5 编辑DID

文章目录 在哪编辑DID的分类编辑快照数据添加 DID 在哪编辑 DID的分类 编辑快照数据 添加 DID

带你用uniapp从零开发一个仿小米商场_9. 轮播图组件封装及使用

导航栏有了,接下来就是轮播图了,轮播图如下, 因为uniapp 官方自己有轮播图,所以这里就不自己写了,直接使用uniapp的轮播图二次开发就好 uniapp的轮播图组件叫swiper ,感兴趣的朋友可以点击链接,直接去看官方文档,也可以看我这里实操 用hbuilderX编译uniapp的代码有一个好处…

redis实现消息延迟队列

业务场景 在很多软件系统功能中都会出现定时任务的业务场景,比如提前点单,比如定时发布动态,文章等而出现这样的的定时的任务为延迟队任务 代码模块 任务的持久化一般都需要建立一个任务表和任务日志表,避免宕机导致任务失效,先新建立一个数据库,创建基本的任务表和任务日志表…

uniapp+vue基于Android的校园二手跳蚤市场的设计与实现 微信小程序

实现功能&#xff1a; 用户管理&#xff1a;登陆、注册、注销、修改密码、上传头像、修改资料 发布与检索&#xff1a;发布商品、模糊搜索、人气排序、价格排序、时间排序、推送商品&#xff08;协同过滤算法实现个性化推荐&#xff09;&#xff0c;最新发布、分类检索 核心交易…

Less 嵌套规则

文章目录 前言描述style.less输出后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Sass和Less &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努力填补技术短板。(如果出现错误&#xff0c;…

【数据中台】开源项目(1)-LarkMidTable

LarkMidTable 是一站式开源的数据中台&#xff0c;实现中台的 基础建设&#xff0c;数据治理&#xff0c;数据开发&#xff0c;监控告警&#xff0c;数据服务&#xff0c;数据的可视化&#xff0c;实现高效赋能数据前台并提供数据服务的产品。 系统演示地址 &#xff1a; www.l…

案例027:基于微信小程序的校园二手平台的设计与实现

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;SSM JDK版本&#xff1a;JDK1.8 数据库&#xff1a;mysql 5.7 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.5.4 小程序框架&#xff1a;uniapp 小程序开发软件&#xff1a;HBuilder X 小程序…

【漏洞复现】熊海cms 存在sql注入 附poc

漏洞描述 熊海CMS 是由熊海开发的一款可广泛应用于个人博客,个人网站,企业网站的一套网站综合管理系统。 其采用前后端整合设计思路,php,Apache,mysql,前端使用Bootstrap和少许jquery前端框架开发; 网站样式设计简洁大方,整体功能点并不多,但功能正好够用;拥有一个…

AI辅助工具

任务拆解工具 Magic ToDo - GoblinTools 可用的AI搜索和对话工具&#xff1a;chatgpt 梦畅AI

打开CMD的六种方法,CMD快捷键,CMD命令大全及详解

目录 前言1. winR快捷键2、通过文本文档创建&#xff1b;3、通过C盘中的cmd.exe文件打开&#xff1b;4、创建快捷方式&#xff1b;5、通过PowerShell打开&#xff1b;6、通过文件夹导航栏打开&#xff1b; 前言 自己的电脑win键失灵了&#xff0c;想通过winR来调出cmd&#xff…

【聚类 | K-means】原理及推导流程(附模板代码,库手撕实现)

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

代码随想录算法训练营第四十八天|121. 买卖股票的最佳时机、122. 买卖股票的最佳时机 II

LeetCode 121. 买卖股票的最佳时机 题目链接&#xff1a;121. 买卖股票的最佳时机 - 力扣&#xff08;LeetCode&#xff09; 直觉告诉我要贪心算法&#xff0c;章节告诉我得用DP来做&#xff0c;行&#xff0c;都做一下&#xff01; 贪心&#xff1a;只能买一次&#xff0c;所…

找不到vcomp120.dll该如何修复?vcomp120.dll丢失的5个可行解决方法

本文将对vcomp120.dll文件的丢失原因进行详细分析&#xff0c;并提供五个有效的修复方法。同时&#xff0c;本文还将深入介绍vcomp120.dll文件的作用及其在程序运行中的重要性。 一、vcomp120.dll文件丢失原因 操作系统损坏&#xff1a;由于病毒感染、系统错误等原因&#xf…

【Spring】Spring事务详解

&#x1f4eb;作者简介&#xff1a;小明java问道之路&#xff0c;2022年度博客之星全国TOP3&#xff0c;专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化&#xff0c;文章内容兼具广度、深度、大厂技术方案&#xff0c;对待技术喜欢推理加验证&#xff0c;就职于…