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 语言中需用用户自己维护

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

name 属性:提高 Vue 应用可维护性的关键

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

Linux加强篇006-存储结构与管理硬盘

目录 前言 1. 从“/”开始 2. 物理设备命名规则 3. 文件系统与数据资料 4. 挂载硬件设备 5. 添加硬盘设备 6. 添加交换分区 7. 磁盘容量配额 8. VDO虚拟数据优化 9. 软硬方式链接 前言 悟已往之不谏&#xff0c;知来者之可追。实迷途其未远&#xff0c;觉今是而昨非…

5.7 Windows驱动开发:取进程模块函数地址

在笔者上一篇文章《内核取应用层模块基地址》中简单为大家介绍了如何通过遍历PLIST_ENTRY32链表的方式获取到32位应用程序中特定模块的基地址&#xff0c;由于是入门系列所以并没有封装实现太过于通用的获取函数&#xff0c;本章将继续延申这个话题&#xff0c;并依次实现通用版…

linux内核态内存泄漏检测-kmemleak

参考文章&#xff1a;Linux内核态内存泄漏检测工具--kmemleak工具原理及应用_linux 内存泄漏检测工具-CSDN博客 细说&#xff5c;Linux 内存泄漏检测实现原理与实现_内核_指针_信息 kmemleak原理&#xff1a;看网上说大概原理是在通过kmalloc&#xff0c;vmalloc&#xff0c…

分布式锁,分布式锁应该具备哪些条件,分布式锁的实现方式有:基于Zookeeper实现、Redis实现、数据库实现

文章目录 分布式锁0-1分布式锁--包含CAP理论模型概述分布式锁&#xff1a;分布式锁应该具备哪些条件&#xff1a;分布式锁的业务场景&#xff1a; 分布式锁的实现方式有&#xff1a;基于Zookeeper - 分布式锁实现思想优缺点基于Redis - 分布式锁实现思想实现思想的具体步骤&…

[AutoSAR存储] 车载存储层次 和 常用存储芯片概述

公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《AutoSAR存储》 <<<< 返回总目录 <<<< 1 存储系统层次 先抛个问题&#xff0c; 为什么要划分存储器的层次&#xff1f; 速度越快&#xff0c;但成本越高&#xff0c;从经济的角度规…

【Web】[GKCTF 2021]easycms

直接点击登录按钮没有反应 扫目录扫出来/admin.php 访问 弱口令admin 12345直接登录成功 点开设计--主题--自定义 编辑页头&#xff0c;类型选择php源代码 点保存显示权限不够 设计--组件--素材库 先随便上传一个文件&#xff0c;之后改文件名称为../../../../../system/tmp…

OSS+CDN的资费和安全

文章目录 花费OSSCDNOSS CDN 安全OSS防盗链跨域设置CORS数据加密 CDN防盗链URL鉴权Cookie鉴权远程鉴权IP黑白名单UA黑白名单 回源服务自定义私有参数IP黑白名单数据加密 花费 OSS 存储费用 &#xff1a;0.12元/GB/月下行流量费用 &#xff1a;0.5元/GB请求费用 &#xff1a;…

2023金盾杯线上赛-AGRT战队-WP

目录 WEB ApeCoin get_source ezupload easyphp MISC 来都来了 芙宁娜 Honor Crypto 我看看谁还不会RSA hakiehs babyrsa PWN sign-format RE Re1 WEB ApeCoin 扫描发现有源码泄露&#xff0c;访问www.tar.gz得到源码。 在源码中发现了冰蝎马。 Md5解码&am…

持续集成部署-k8s-配置与存储-存储类:动态创建NFS-PV案例

动态创建NFS-PV案例 1. 前置条件2. StorageClass 存储类的概念和使用3. RBAC 配置4. storageClass 配置5. 创建应用&#xff0c;测试 PVC 的自动配置6. 解决 PVC 为 Pending 状态问题7. 单独测试自动创建 PVC 1. 前置条件 这里使用 NFS 存储的方式&#xff0c;来演示动态创建 …

springboot打印启动信息

打印启动信息 转载自:www.javaman.cn 1 spring Bean实例化流程 基本流程&#xff1a; 1、Spring容器在进行初始化时&#xff0c;会将xml或者annotation配置的bean的信息封装成一个BeanDefinition对象&#xff08;每一个bean标签或者bean注解都封装成一个BeanDefinition对象&a…

传输层协议[精选]

网络: 跨主机通信. 互联网通信: 两点之间的通信路径有无数条. 集线器: 把一根网线差出来两根,但是同一时刻只能有一根线跑.交换机: 组建局域网.路由器: 本质就是将两个局域网连接起来 交换机和路由器之间的区别越来越模糊. 调制解调器: 使用电话线上网的时候,需要将电话线的模…

推动卓越创新:了解 4 种研发团队架构如何优化您的组织

揭示敏捷实践中常犯的12大错误&#xff0c;了解如何避免这些敏捷失败 陷阱&#xff0c;找出问题根源并采取有效改进措施&#xff0c;提高项目成功率。立即连线 Runwise.co 社区敏捷专家获得专业建议&#xff0c;或 Runwise.co 在线学习敏捷方法实战课程&#xff0c;提升您和团队…

Node——Node.js基础

Node.js是一个基于Chrome V8引擎的JavaScript运行时环境&#xff0c;它能够让JavaScript脚本运行在服务端&#xff0c;这使得JavaScript成为与PHP、Python等服务端语言平起平坐的脚本语言。 1、认识Node.js Node.js是当今网站开发中非常流行的一种技术&#xff0c;它以简单易…

【go入门】表单

4.1 处理表单的输入 先来看一个表单递交的例子&#xff0c;我们有如下的表单内容&#xff0c;命名成文件login.gtpl(放入当前新建项目的目录里面) <html> <head> <title></title> </head> <body> <form action"/login" meth…

11-25碎片小知识

一.strlen补充 strlen函数返回值是size_t&#xff0c;即无符号整型&#xff0c; size_t有头文件&#xff0c;是stdio.h 由于strlen函数返回值是无符号整型&#xff0c;所以下面代码要注意 -3会被转换成无符号的 实现my_strlen 法一&#xff1a;指针减指针 #define _CRT_S…

uniapp IOS从打包到上架流程(详细简单)

​ uniapp IOS从打包到上架流程&#xff08;详细简单&#xff09; 原创 1.登入苹果开发者网站&#xff0c;打开App Store Connect ​ 2.新App的创建 点击我的App可以进入App管理界面&#xff0c;在右上角点击➕新建App 即可创建新的App&#xff0c;如下图&#xff1a; ​ 3.…

MetaObject-BeanWrapper-MetaClass-Reflector的关系

MetaObject、BeanWrapper、MetaClass、Reflector之间是通过装饰器模式逐层进行装饰的。其中MetaObject、BeanWrapper是操作对象&#xff1b;MetaClass、Reflector是操作Class ObjectWrapper类结构图 BaseWrapper是对BeanWrapper、MapWrapper公共方法的提取及类图的优化&#…

057-第三代软件开发-文件监视器

第三代软件开发-文件监视器 文章目录 第三代软件开发-文件监视器项目介绍文件监视器实现原理关于 QFileSystemWatcher实现代码 关键字&#xff1a; Qt、 Qml、 关键字3、 关键字4、 关键字5 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&…

京东秒杀之商品列表

1 在gitee上添加.yml文件 1.1 添加good-server.yml文件 server:port: 8084 spring:datasource:url: jdbc:mysql://localhost:3306/shop_goods?serverTimezoneGMT%2B8driverClassName: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourceusername: rootpa…