C++编程:进阶阶段—4.2对象
目录
4.2 对象特征
4.2.1 构造函数和析构函数
4.2.2 构造函数的分类
4.2.3 拷贝函数调用时机
4.2.4 构造函数调用规则
4.2.5 深拷贝与浅拷贝
4.2.6 初始化列表
4.2.7 类对象作为类成员
4.2.8 静态成员
4.2.9 成员变量和成员函数的存储
4.2.10 this指针
4.2.11 空指针访问成员函数
4.2.12 const修饰成员函数
4.2 对象特征
对象的初始化和清理:C++中,每个对象都有初始设置和对象销毁前的清理数据的设置。
4.2.1 构造函数和析构函数
C++中利用构造函数和析构函数对对象进行初始化和清理。这两个函数会被编译器自动调用,完成对象的初始化和清理。如果程序员不提供构造和析构,编译器会提供构造函数和析构函数,但是是空的。
构造函数:创建对象时为对象的成员属性赋值,构造函数由编译器自动调用,无须手动调用。
语法:类名(){}
1.构造函数,没有返回值也不写void;
2.函数名与类名相同;
3.构造函数可以有参数,因此可以发生重载;
4.程序在调用对象时会自动调用构造,无须手动调用,且只调用一次。
析构函数:对象销毁前系统自动调用,执行一些清理工作。
语法:~类名(){}
1.析构函数,没有返回值也不写void;
2.函数名与类名相同,在函数名前加上符号~;
3.析构函数不可以有函数,因此不可以发生重载;
4.程序在对象销毁前会自动调用析构,无须手动调用,且只调用一次。
代码如下:
#include <iostream>
using namespace std;class Person
{
public://构造函数 初始化对象Person(){cout<<"Person构造函数的调用"<<endl;}//析构函数 销毁/清理对象~Person(){cout<<"Person析构函数的调用"<<endl;}
};void test01()
{Person p;//栈上的数据,该函数执行完后,p这个对象会被释放
}int main()
{//对象的初始化和清理test01();Person p;system("pause");return 0;
}
输出如下:

4.2.2 构造函数的分类
按参数分:有参构造、无参构造;
按类型分:普通构造、拷贝构造。
调用方式:括号法、显示法、隐式转换法。
代码如下:
#include <iostream>
using namespace std;//构造函数发分类及调用
class Person
{
public://无参(默认)构造Person(){cout<<"Person的无参构造函数的调用"<<endl;}//有参构造Person(int a){age=a;cout<<"Person的有参构造函数的调用"<<endl;}//拷贝构造函数(将Person p的属性拷贝过来)Person(const Person &p){age=p.age;cout<<"Person的拷贝构造函数的调用"<<endl;}~Person(){cout<<"Person析构函数的调用"<<endl;}private:int age;
};void test01()
{//调用:括号法cout<<"括号法调用构造函数:"<<endl;Person p1;//默认构造函数调用,不用加括号,编译器会认为Person p1();是一个函数声明。Person p2(21);//有参构造函数调用Person p3(p2);//拷贝构造函数调用//调用:显示法cout<<"显示法调用构造函数:"<<endl;Person p4;Person p5=Person(21);//有参构造Person P6=Person(p5);//拷贝构造Person(21);//表示一个匿名对象,在等式左边的P2就是给他取的名字,匿名对象执行后会立即回收。cout<<"匿名对象清理后执行了这句代码"<<endl;//PS:不要用拷贝构造 初始化匿名对象,编译器会认为Person(p3);是一个对象声明Person p3;//Person(p3);//调用:隐式转换法cout<<"显示法调用构造函数:"<<endl;Person p7=21;//有参构造Person p8=p7;//拷贝构造
}int main()
{test01();return 0;
}
输出如下:

4.2.3 拷贝函数调用时机
- 使用一个已经创建完毕的对象来初始化一个新对象;
- 值传递的方式给函数参数传值;
- 以值方式返回局部对象。
代码如下:
#include <iostream>
using namespace std;//拷贝构造函数调用时机
class Person
{
public://无参(默认)构造Person(){cout<<"Person的无参构造函数的调用"<<endl;}//有参构造Person(int a){age=a;cout<<"Person的有参构造函数的调用"<<endl;}//拷贝构造函数Person(const Person &p){age=p.age;cout<<"Person的拷贝构造函数的调用"<<endl;}~Person(){cout<<"Person析构函数的调用"<<endl;}int age;
};//使用一个已经创建完毕的对象来初始化一个新对象
void test01()
{cout<<"test01函数调用"<<endl;Person p1(21);Person p2(p1);cout<<"p2的年龄为:"<<p2.age<<endl;
}//值传递的方式给函数参数传值
void doWork(Person p)
{}void test02()
{cout<<"test02函数调用"<<endl;Person p;doWork(p);//这里传入的p和dowork中的p不一样
}//以值方式返回局部对象
Person doWork2()
{Person p1;cout<<"p1的地址为:"<<(long long)&p1<<endl;return Person(p1);//直接返回p1则不会调用拷贝函数,因为编译器自动做了优化(可以看到p1和p的地址一样)
}void test03()
{cout<<"test03函数调用"<<endl;Person p=doWork2();cout<<"p的地址为:"<<(long long)&p<<endl;
}int main()
{test01();test02();test03();return 0;
}
输出如下:

4.2.4 构造函数调用规则
默认情况下,C++编译器至少给类添加三个函数;
- 1.默认构造函数(无参,函数体为空)
- 2.默认析构函数(无参,函数体为空)
- 3.默认拷贝构造函数,对属性进行值拷贝
调用规则:
- 如果用户定义了有参构造函数,则编译器不提供默认无参构造,但会提供默认拷贝构造
- 如果用户定义了拷贝构造函数,则编译器不再提供其他构造函数
代码如下:
#include <iostream>
using namespace std;class Person
{
public:// Person()// {// cout<<"person的默认构造函数"<<endl;// }Person(int a){age=a;cout<<"Person的有参构造函数的调用"<<endl;}// Person(const Person &p)// {// age=p.age;// cout<<"Person的拷贝构造函数的调用"<<endl;// }~Person(){cout<<"Person析构函数的调用"<<endl;}int age;
};// void test01()
// {
// Person p;
// p.age=18;// Person p2(p);
// cout<<"p2的年龄为:"<<p2.age<<endl;
// }void test02()
{Person p(28);Person p2(p);cout<<"p2的年龄为:"<<p2.age<<endl;
}int main()
{//test01();test02();return 0;
}
输出如下:用户定义了拷贝构造函数

输出如下:用户没有定义拷贝构造函数

错误示例:用户定义了有参构造,但没有定义无参(默认)构造,则编译器也不会提供默认构造,此时调用默认构造则会报错。

输出如下:用户只定义了有参构造,则编译器依然或提供拷贝构造

4.2.5 深拷贝与浅拷贝
浅拷贝:编译器提供的拷贝函数,简单的赋值拷贝操作;
缺点:容易导致堆区的重复释放,利用深拷贝解决。
深拷贝:在堆区重新申请空间,进行拷贝操作,而不是与被拷贝的指针指向相同的空间。
PS:如果属性有在堆区开辟的,一定要自己定义拷贝构造函数,防止浅拷贝中出现的问题。
代码如下:
#include <iostream>
using namespace std;class Person
{
public:Person(){cout<<"person的默认构造函数"<<endl;}Person(int a,int h){age=a;height=new int(h);cout<<"Person的有参构造函数的调用"<<endl;}//自己实现拷贝构造函数,解决浅拷贝的问题Person(const Person &p){age=p.age;height=p.height;//编译器写的(浅拷贝)height= new int(*p.height);//深拷贝操作,另外开辟空间cout<<"Person的拷贝构造函数的调用"<<endl;}~Person(){//析构的作用,将堆区new的数据手动释放if(height!=NULL)//若指针不为空,则需要释放{delete height;//P2先释放,完了之后P也需要释放,但两个对象的指针操作的是同一个堆区中的地址,造成重复释放的非法操作,因此会报错height=NULL;//防止野指针出现,将指针置空}cout<<"Person析构函数的调用"<<endl;}int age;int * height;
};void test01()
{Person p(28,160);Person p2(p);cout<<"p2的年龄为:"<<p2.age<<" 身高为:"<<*p2.height<<endl;
}int main()
{test01();return 0;
}
输出如下:

4.2.6 初始化列表
作用:C++提供了初始化列表语法,用来初始化属性。
语法:构造函数():属性1(值1),属性2(值2)...{}
代码如下:
#include <iostream>
using namespace std;class Person
{
public://传统初始化操作// Person(int a,int b,int c)// {// A=a;// B=b;// C=c;// }//初始化列表赋初值//Person():A(1),B(2),C(3){}Person(int a,int b,int c):A(a),B(b),C(c){}int A;int B;int C;
};void test01()
{//Person p(10,20,30);//传统赋值Person p(1,2,3);//列表赋值cout<<"A="<<p.A<<endl;cout<<"B="<<p.B<<endl;cout<<"C="<<p.C<<endl;}int main()
{test01();return 0;
}
输出如下:
![]()
4.2.7 类对象作为类成员
C++中类的成员可以是另一个类的对象,称为对象成员。
注意对象作为成员时,两种对象的构造和析构函数的顺序。(先构造其他类,再构造本类,先析构本类,再析构其他类)
代码如下:
#include <iostream>
using namespace std;
#include <string>//对象成员
class Phone
{
public://手机品牌string PName;Phone(string pname){cout<<"Phone的构造函数的调用"<<endl;PName=pname;}~Phone(){cout<<"Phone析构函数的调用"<<endl;}
};class Person
{
public://P(pname)相当于Phone P=pname; 隐式转换法Person(string name,string pname):Name(name),P(pname){cout<<"Person的构造函数的调用"<<endl;}~Person(){cout<<"Person析构函数的调用"<<endl;}string Name;Phone P;
};void test01()
{Person p("张三","iPhone18");cout<<p.Name<<"拿着"<<p.P.PName<<endl;
}int main()
{test01();return 0;
}
输出如下:

4.2.8 静态成员
静态成员是指在成员变量和成员函数卡加static关键字,静态成员都有三种访问权限。
静态成员变量:
- 所有对象共享同一份数据
- 在编译阶段分配内存(程序运行前)
- 类内声明,类外初始化
静态成员函数
- 所有对象共享同一个函数
- 静态成员函数只能访问静态成员变量
代码如下:
#include <iostream>
using namespace std;
#include <string>//静态成员
class Person
{
public://静态成员变量static int A;//类内声明int B;//静态成员函数static void func(){A=44;//B=22;//静态成员函数访问非静态成员变量,报错,无法区分是哪个对象的Bcout<<"静态成员函数调用"<<endl;}
};//类外初始化
int Person::A=100;void test01()
{Person p;cout<<p.A<<endl;Person p2;p2.A=200;//所有对象共享同一份数据,因此有两种访问方式:通过对象访问;通过类名访问cout<<p.A<<endl;cout<<Person::A<<endl;
}void test02()
{//两种访问方式:通过对象访问;通过类名访问Person p;p.func();Person::func();cout<<p.A<<endl;
}int main()
{test01();test02();return 0;
}
输出如下:

错误示例:静态成员函数访问非静态成员变量

4.2.9 成员变量和成员函数的存储
类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上的。
代码如下:
#include <iostream>
using namespace std;
#include <string>//静态成员
class Person1
{};class Person2
{int A;//非静态成员变量
};class Person3
{int A;static int B;//静态成员变量
};int Person3::B=9;class Person4
{int A;static int B;void func(){}//非静态成员函数
};class Person5
{int A;static int B;void func(){}//非静态成员函数static void func2(){};
};void test01()
{Person1 p1;//空对象占用内存为1,为了区分空对象占内存的位置,每个空对象有一个唯一的地址cout<<"size of p1="<<sizeof(p1)<<endl;Person2 p2;//有非静态成员变量,占4字节 属于类的对象上的数据cout<<"size of p2="<<sizeof(p2)<<endl;Person3 p3;//有静态成员变量 不属于类的对象上的数据cout<<"size of p3="<<sizeof(p3)<<endl;Person4 p4;//非静态成员函数 不属于类的对象上的数据cout<<"size of p4="<<sizeof(p4)<<endl;Person5 p5;//静态成员函数 不属于类的对象上的数据cout<<"size of p5="<<sizeof(p5)<<endl;
}int main()
{test01();return 0;
}
输出如下:

4.2.10 this指针
每一个非静态成员函数只会产生一个函数实例,所有同类中的多个对象会公用一块代码。
C++提供this指针来指向被调用的成员函数所属的对象。this指针是隐含每一个非静态成员函数内的一种指针,不需要定义,直接使用即可。
用途:
- 当形参和成员变量同名时,用this指针来区分
- 在类的非静态成员函数中返回对象本身,可使用return *this。
PS:用Person&定义返回值类型,是因为可以一直对同一个空间操作,用Person定义返回值类型表示值返回,会复制一份新的数据(按照本体p2创建了新的数据,而不是返回的p2本体),调用了拷贝构造函数。
代码如下:
#include <iostream>
using namespace std;
#include <string>class Person
{
public:int age;Person(int age){//age=age;//报错//this指针指向被调用的成员函数所属的对象p1this->age=age;}
//用Person&定义返回值类型,是因为可以一直对同一个空间操作,用Person定义返回值类型表示值返回,会复制一份新的数据(按照本体p2创建了新的数据,而不是返回的p2本体),调用了拷贝构造函数Person& PersonAddAge(Person &p){this->age+=p.age;//this指向p2的指针,*p2指向p2本体return *this;}
};//解决名称冲突
void test01()
{Person p1(18);cout<<p1.age<<endl;
}//用*this 返回对象本身
void test02()
{Person p1(31);Person p2(31);p2.PersonAddAge(p1);cout<<p2.age<<endl;p2.PersonAddAge(p1).PersonAddAge(p1);//用this*返回才能链式追加cout<<p2.age<<endl;}int main()
{test01();test02();return 0;
}
输出如下:

错误示例:名称冲突,形参和属性名相同时,不能输出正确结果

4.2.11 空指针访问成员函数
C++中空指针可以调用成员函数,但需要注意有没有用this指针。如果用到this指针,需要加以判断保证代码的健壮性。
代码如下:
#include <iostream>
using namespace std;//空指针调用成员函数
class Person
{
public:void showClassName(){cout<<"this is person class"<<endl;}void showPersonAge(){if(this==NULL){return;}//传入指针为空,报错 在前面加一个空指针的判断cout<<"age="<<this->age<<endl;}int age;
};void test01()
{Person *p=NULL;p->showClassName();p->showPersonAge();
}int main()
{test01();return 0;
}
输出如下:
![]()
错误示例:用空指针访问属性,图中age,默认是this->age,而访问时用的空指针,this为空所以不能指向正确的对象的属性。

4.2.12 const修饰成员函数
常函数:
- 成员函数后加const后称为常函数;
- 常函数内不可用修改成员属性;
- 成员属性声明时加关键词mutable后,在常函数中依然可以修改
常对象:
- 声明对象前加const称该对象为常对象;
-
常对象不允许修改指针指向的值;
- 常对象只能调用常函数
代码如下:
#include <iostream>
using namespace std;//常函数
class Person
{
public://this指针的本质是一个指针常量Person * const this 指针的指向是不可修改的//后面加的const相当于const Person * const this,使this指向的值也不可修改void showPerson() const{this->b=99;//this=NULL;//this的指针指向不能修改cout<<"this is person class"<<endl;}Person(){}//不写默认构造函数会报错实例化的常对象没有初始化void func(){}int age;mutable int b;
};void test01()
{Person p;p.showPerson();
}void test02()
{const Person p;//p.age=99;//报错 常对象不允许修改指针指向的值p.b=88;p.showPerson();//p.func();//报错 常对象不能调用非常函数
}int main()
{test01();test02();return 0;
}
相关文章:
C++编程:进阶阶段—4.2对象
目录 4.2 对象特征 4.2.1 构造函数和析构函数 4.2.2 构造函数的分类 4.2.3 拷贝函数调用时机 4.2.4 构造函数调用规则 4.2.5 深拷贝与浅拷贝 4.2.6 初始化列表 4.2.7 类对象作为类成员 4.2.8 静态成员 4.2.9 成员变量和成员函数的存储 4.2.10 this指针 4.2.11 空指针…...
决策树的核心思想
一、决策树的核心思想 本质:通过特征判断对数据集递归划分,形成树形结构。目标:生成一组“若-则”规则,使数据划分到叶子节点时尽可能纯净。关键流程: 特征选择:选择最佳分裂特征(如信息增益最…...
TensorFlow.js 全面解析:在浏览器中构建机器学习应用
TensorFlow.js 全面解析:在浏览器中构建机器学习应用 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 文章目录 TensorFlow.js 全面解析&#x…...
CI/CD—Jenkins配置Poll SCM触发自动构建
Poll SCM简介 在 Jenkins 等持续集成工具中,“Poll SCM” 是一种用于轮询软件配置管理(SCM)系统以检查代码变更的机制,以下是对它的详细介绍: 作用 “Poll SCM” 允许 Jenkins 定期检查指定的 SCM 系统(如 …...
《云原生技术:DeepSeek分布式推理的效能倍增器》
在当今人工智能飞速发展的时代,大语言模型的推理能力成为了衡量其性能的关键指标。DeepSeek作为人工智能领域的重要参与者,致力于提升模型的推理效率和准确性。而云原生技术的出现,为DeepSeek实现更高效的分布式推理提供了强大的支持。 云原…...
AI与SEO关键词智能解析
内容概要 人工智能技术正重塑搜索引擎优化的底层逻辑,其核心突破体现在关键词解析维度的结构性升级。通过机器学习算法对海量搜索数据的动态学习,AI不仅能够识别传统TF-IDF模型中的高频词汇,更能捕捉语义网络中隐含的关联特征。下表展示了传…...
OpenHarmony子系统开发 -- 构建系统编码规范与最佳实践
OpenHarmony子系统开发 -- 构建系统编码规范与最佳实践 概述 gn是generate ninja的缩写,它是一个元编译系统(meta-build system),是ninja的前端,gn和ninja结合起来,完成OpenHarmony操作系统的编译任务。 gn简介 目…...
1-002:MySQL InnoDB引擎中的聚簇索引和非聚簇索引有什么区别?
在 MySQL InnoDB 存储引擎 中,索引主要分为 聚簇索引(Clustered Index) 和 非聚簇索引(Secondary Index)。它们的主要区别如下: 1. 聚簇索引(Clustered Index) 定义 聚簇索引是表数…...
STM32之BKP
VBAT备用电源。接的时候和主电源共地,正极接在一起,中间连接一个100nf的电容。BKP是RAM存储器。 四组VDD都要接到3.3V的电源上,要使用备用电池,就把电池正极接到VBAT,负极跟主电源共地。 TEMPER引脚先加一个默认的上拉…...
c++的基础排序算法
一、快速排序 1. 选择基准值(Pivot) 作用 :从数组中选择一个元素作为基准(Pivot),用于划分数组。常见选择方式 : 固定选择最后一个元素(如示例代码)。随机选择…...
基于Spring3的抽奖系统
注:项目git仓库地址:demo.lottery 小五Z/Spring items - 码云 - 开源中国 目录 注:项目git仓库地址:demo.lottery 小五Z/Spring items - 码云 - 开源中国 项目具体代码可参考仓库源码,本文只讲解重点代码逻辑 一…...
基于qiime2的16S数据分析全流程:从导入数据到下游分析一条龙
目录 创建metadata 把数据导入qiime2 去除引物序列 双端合并 (dada2不需要) 质控 (dada2不需要) 使用deblur获得特征序列 使用dada2生成代表序列与特征表 物种鉴定 可视化物种鉴定结果 构建进化树(ITS一般不构建进化树…...
【Linux系统编程】基本IO函数
目录 1、open 函数2、create 函数3、write 函数4、read 函数5、lseek 函数6、access 函数7、unlink 函数8、remove 函数9、fcntl 函数写锁互斥锁示例读锁共享锁示例 1、open 函数 头文件 #include<sys/types.h> #include<sys/stat.h>#include<fcntl.h>…...
Deepseek应用技巧-chatbox搭建前端问答
目标:书接上回,由于本地私有化部署了deepseek的大模型,那怎么能够投入生产呢,那就必须有一个前端的应用界面,好在已经有很多的前人已经帮我们把前段应用给搭建好了,我们使用就可以啦,今天我们就…...
OpenAI API模型ChatGPT各模型功能对比,o1、o1Pro、GPT-4o、GPT-4.5调用次数限制附ChatGPT订阅教程
本文包含OpenAI API模型对比页面以及ChatGPT各模型功能对比表 - 截至2025最新整理数据:包含模型分类及描述;调用次数限制; 包含模型的类型有: Chat 模型(如 GPT-4o、GPT-4.5、GPT-4)专注于对话,…...
Fast DDS Security--秘钥交换
Fast DDS Security模块中默认使用Diffie-Hellman算法进行秘钥交换。Diffie-Hellman 算法(简称 DH 算法)是一个非常重要的加密协议,用于在不安全的通信通道中安全地交换密钥。该算法通过利用数学中的离散对数问题来生成共享密钥,使…...
从0开始的操作系统手搓教程33:挂载我们的文件系统
目录 代码实现 添加到初始化上 上电看现象 挂载分区可能是一些朋友不理解的——实际上挂载就是将我们的文件系统封装好了的设备(硬盘啊,SD卡啊,U盘啊等等),挂到我们的默认分区路径下。这样我们就能访问到了ÿ…...
基于muduo+mysql+jsoncpp的简易HTTPWebServer
一、项目介绍 本项目基于C语言、陈硕老师的muduo网络库、mysql数据库以及jsoncpp,服务器监听两个端口,一个端口用于处理http请求,另一个端口用于处理发送来的json数据。 此项目在实现时,识别出车牌后打包为json数据发送给后端服务…...
【Go学习实战】03-2-博客查询及登录
【Go学习实战】03-2-博客查询及登录 读取数据库数据初始化数据库首页真实数据分类查询分类查询测试 文章查询文章查询测试 分类文章列表测试 登录功能登录页面登录接口获取json参数登录失败测试 md5加密jwt工具 登录成功测试 文章详情测试 读取数据库数据 因为我们之前的数据都…...
《Python实战进阶》No20: 网络爬虫开发:Scrapy框架详解
No20: 网络爬虫开发:Scrapy框架详解 摘要 本文深入解析Scrapy核心架构,通过中间件链式处理、布隆过滤器增量爬取、Splash动态渲染、分布式指纹策略四大核心技术,结合政府数据爬取与动态API逆向工程实战案例,构建企业级爬虫系统。…...
2021 年 9 月青少年软编等考 C 语言六级真题解析
目录 T1. 合法出栈序列思路分析T2. 奇怪的括号思路分析T3. 区间合并思路分析T4. 双端队列思路分析T1. 合法出栈序列 题目链接:SOJ D1110 给定一个由不同小写字母构成的长度不超过 8 8 8 的字符串 x x x,现在要将该字符串的字符依次压入栈中,然后再全部弹出。要求左边的字…...
Linux:多线程(单例模式,其他常见的锁,读者写者问题)
目录 单例模式 什么是设计模式 单例模式介绍 饿汉实现方式和懒汉实现方式 其他常见的各种锁 自旋锁 读者写者问题 逻辑过程 接口介绍 单例模式 什么是设计模式 设计模式就是一些大佬在编写代码的过程中,针对一些经典常见场景,给定对应解决方案&…...
shell 脚本的编写学习
学习编写 Shell 脚本是 Linux/Unix 系统管理和自动化的一个非常有用的技能。Shell 脚本是一些 Shell 命令的集合,用户可以用它来自动执行任务、简化工作流程、管理系统等。下面是一个 Shell 脚本学习的入门指南: 1. Shell 脚本基础 Shell 脚本通常是以…...
【氮化镓】高输入功率应力诱导的GaN 在下的退化LNA退化
2019年,中国工程物理研究院电子工程研究所的Tong等人基于实验与第一性原理计算方法,研究了Ka波段GaN低噪声放大器(LNA)在高输入功率应力下的退化机制。实验结果表明,在27 GHz下施加1 W连续波(CW)输入功率应力后,LNA的增益下降约1 dB,噪声系数(NF)增加约0.7 dB。进一…...
根据开始和结束日期,获取每一天和每个月的开始和结束日期的list
获取开始日期与结束日期之间每天的list /*** 根据传入的开始时间和结束时间,筛选出所有的天的list;** param startTime* param endTime*/public Map<String, List<String>> fetchDayListBetweenStartAndEnd(String startTime, String endTime) {// 创建mapMap<…...
Javaweb后端文件上传@value注解
文件本地存储磁盘 阿里云oss准备工作 阿里云oss入门程序 要重启一下idea,上面有cmd 阿里云oss案例集成 优化 用spring中的value注解...
git规范提交之commitizen conventional-changelog-cli 安装
一、引言 使用规范的提交信息可以让项目更加模块化、易于维护和理解,同时也便于自动化工具(如发布工具或 Changelog 生成器)解析和处理提交记录。 通过编写符合规范的提交消息,可以让团队和协作者更好地理解项目的变更历史和版本…...
Java/Kotlin逆向基础与Smali语法精解
1. 法律警示与道德边界 1.1 司法判例深度剖析 案例一:2021年某游戏外挂团伙刑事案 犯罪手法:逆向《王者荣耀》通信协议,修改战斗数据包 技术细节:Hook libil2cpp.so的SendPacket函数 量刑依据:非法经营罪ÿ…...
非软件开发项目快速上手:14款管理软件精选
文章介绍了以下14款项目管理系统:1.Worktile;2.Teambition;3.Microsoft Project;4.Forbes;5.WorkOtter;6.Trello;7.Smartsheet;8.Taiga;9.ClickUp;10.Monday.…...
Redis四种模式在Spring Boot框架下的配置
在Spring Boot框架下配置Redis的四种模式(单机模式、主从模式、哨兵模式、集群模式)可以通过以下方式实现: 1. 单机模式 在application.properties或application.yml中配置Redis的连接信息: # application.properties spring.redi…...
