C++核心知识(三)—— 静态成员(变量、函数、const成员)、面向对象模型(this指针、常函数、常对象)、友元、数组类、单例模式
【上一篇】C++核心知识(二)—— 类和对象(类的封装)、对象的构造和析构(浅拷贝、深拷贝、explicit、动态分配内存)
1. 静态成员
在类定义中,它的成员(包括成员变量和成员函数),这些成员可以用关键字static声明为静态的,称为静态成员。
不管这个类创建了多少个对象,静态成员只有一个拷贝,这个拷贝被所有属于这个类的对象共享。
1.1 静态成员变量
在一个类中,若将一个成员变量声明为static,这种成员称为静态成员变量。与一般的数据成员不同,无论建立了多少个对象,都只有一个静态数据的拷贝。静态成员变量,属于某个类,所有对象共享。
静态变量,是在编译阶段就分配空间,对象还没有创建时,就已经分配空间。
静态成员变量必须在类中声明,在类外定义。
静态数据成员不属于某个对象,在为对象分配空间中不包括静态成员所占空间。
静态数据成员可以通过类名或者对象名来引用。
class Person{
public://类的静态成员属性static int sNum;
private:static int sOther;
};//类外初始化,初始化时不加static
int Person::sNum = 0;
int Person::sOther = 0;
int main(){//1. 通过类名直接访问Person::sNum = 100;cout << "Person::sNum:" << Person::sNum << endl;//2. 通过对象访问Person p1, p2;p1.sNum = 200;cout << "p1.sNum:" << p1.sNum << endl;cout << "p2.sNum:" << p2.sNum << endl;//3. 静态成员也有访问权限,类外不能访问私有成员//cout << "Person::sOther:" << Person::sOther << endl;Person p3;//cout << "p3.sOther:" << p3.sOther << endl;system("pause");return EXIT_SUCCESS;
}1.2 静态成员函数
在类定义中,前面有static说明的成员函数称为静态成员函数。静态成员函数使用方式和静态变量一样,同样在对象没有创建前,即可通过类名调用。静态成员函数主要为了访问静态变量,但是,不能访问普通成员变量。
静态成员函数的意义,不在于信息共享,数据沟通,而在于管理静态数据成员,完成对静态数据成员的封装。
静态成员函数只能访问静态变量,不能访问普通成员变量
静态成员函数的使用和静态成员变量一样
静态成员函数也有访问权限
普通成员函数可访问静态成员变量、也可以访问非静态成员变量
class Person{
public://普通成员函数可以访问static和non-static成员属性void changeParam1(int param){mParam = param;sNum = param;}//静态成员函数只能访问static成员属性static void changeParam2(int param){//mParam = param; //无法访问sNum = param;}
private:static void changeParam3(int param){//mParam = param; //无法访问sNum = param;}
public:int mParam;static int sNum;
};//静态成员属性类外初始化
int Person::sNum = 0;int main(){//1. 类名直接调用Person::changeParam2(100);//2. 通过对象调用Person p;p.changeParam2(200);//3. 静态成员函数也有访问权限//Person::changeParam3(100); //类外无法访问私有静态成员函数//Person p1;//p1.changeParam3(200);return EXIT_SUCCESS;
}1.3 const静态成员属性
如果一个类的成员,既要实现共享,又要实现不可改变,那就用static const 修饰。定义静态const数据成员时,最好在类内部初始化。
class Person{
public://static const int mShare = 10;const static int mShare = 10; //只读区
};
int main(){cout << Person::mShare << endl;//Person::mShare = 20;return EXIT_SUCCESS;
}1.4 单例模式
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

Singleton(单例):在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;为了防止在外部对其实例化,将其默认构造函数和拷贝构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。
实现单例模式的思路:
1.把无参构造函数和拷贝构造函数私有化
2.定义一个类内的静态成员指针
3.在类外初始化时,new一个对象
4.把指针的权限设置为私有,然后提供一个静态成员函数让外面获取这个指针
用单例模式,模拟公司员工使用打印机场景,打印机可以打印员工要输出的内容,并且可以累积打印机使用次数。
class Printer{
public://4.静态成员函数,访问静态成员变量static Printer* getInstance(){ return pPrinter;}void PrintText(string text){cout << "打印内容:" << text << endl;cout << "已打印次数:" << mTimes << endl;cout << "--------------" << endl;mTimes++;}
//1.把构造函数私有化(拷贝构造也要私有化)
private:Printer(){ mTimes = 0; }Printer(const Printer&){}
private://2.定义一个类内的静态成员指针static Printer* pPrinter;int mTimes;
};
//3.在类外初始化时,new一个对象
Printer* Printer::pPrinter = new Printer; //这里可以new是因为在Printer::作用域,编译器把它当成在类内void test(){Printer* printer = Printer::getInstance();printer->PrintText("离职报告!");printer->PrintText("入职合同!");printer->PrintText("提交代码!");
}2. C++面向对象模型初探
2.1 成员变量和函数的存储
在c语言中, 变量和函数“分开来声明的,也就是说,语言本身并没有支持“数据”和“函数”之间的关联性我们把这种程序方法称为“程序性的”,由一组“分布在各个以功能为导航的函数中”的算法驱动,它们处理的是共同的外部数据。
c++实现了“封装”,那么数据(成员属性)和操作(成员函数)是什么样的呢?
“数据”和“处理数据的操作(函数)”是分开存储的。
c++中的非静态数据成员直接内含在类对象中,就像c struct一样。
成员函数(member function)虽然内含在class声明之内,却不出现在对象中。
每一个非内联成员函数(non-inline memberfunction)只会诞生一份函数实例。
class MyClass01{
public:int mA;
};class MyClass02{
public:int mA;static int sB;
};class MyClass03{
public:void printMyClass(){cout << "hello world!" << endl;}
public:int mA;static int sB;
};class MyClass04{
public:void printMyClass(){cout << "hello world!" << endl;}static void ShowMyClass(){cout << "hello world!" << endl;}
public:int mA;static int sB;
};int main(){MyClass01 mclass01;MyClass02 mclass02;MyClass03 mclass03;MyClass04 mclass04;cout << "MyClass01:" << sizeof(mclass01) << endl; //4//静态数据成员并不保存在类对象中cout << "MyClass02:" << sizeof(mclass02) << endl; //4//非静态成员函数不保存在类对象中cout << "MyClass03:" << sizeof(mclass03) << endl; //4//静态成员函数也不保存在类对象中cout << "MyClass04:" << sizeof(mclass04) << endl; //4return EXIT_SUCCESS;
}空类的大小是1.
类的成员函数不占用类的大小,静态成员变量不占用类的大小,静态成员函数不占用类的大小
普通成员变量占用类的大小
类的成员中,成员函数和成员变量是分开存储
2.2 this指针
2.2.1 this指针工作原理
通过上例我们知道,c++的数据和操作也是分开存储,并且每一个非内联成员函数(non-inlinemember function)只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码。
那么问题是:这一块代码是如何区分那个对象调用自己的呢?

c++通过提供特殊的对象指针,this指针,解决上述问题。This指针指向被调用的成员函数所属的对象。
c++规定,this指针是隐含在对象成员函数内的一种指针。当一个对象被创建后,它的每一个成员函数都含有一个系统自动生成的隐含指针this,用以保存这个对象的地址,也就是说虽然我们没有写上this指针,编译器在编译的时候也是会加上的。因此this也称为“指向本对象的指针”,this指针并不是对象的一部分,不会影响sizeof(对象)的结果。
this指针是C++实现封装的一种机制,它将对象和该对象调用的成员函数连接在一起,在外部看来,每一个对象都拥有自己的函数成员。一般情况下,并不写this,而是让系统进行默认设置。
this指针永远指向当前对象。
成员函数通过this指针即可知道操作的是那个对象的数据。This指针是一种隐含指针,它隐含于每个类的非静态成员函数中。This指针无需定义,直接使用即可。
注意:静态成员函数内部没有this指针,静态成员函数不能操作非静态成员变量。
c++编译器对普通成员函数的内部处理 |
![]() |
2.2.2 this指针的使用
当形参和成员变量同名时,可用this指针来区分
在类的非静态成员函数中返回对象本身,可使用return *this.
class Person{
public://1. 当形参名和成员变量名一样时,this指针可用来区分Person(string name,int age){//name = name;//age = age; //输出错误this->name = name;this->age = age;}//2. 返回对象本身的引用//重载赋值操作符//其实也是两个参数,其中隐藏了一个this指针Person PersonPlusPerson(Person& person){string newname = this->name + person.name;int newage = this->age + person.age;Person newperson(newname, newage);return newperson;}void ShowPerson(){cout << "Name:" << name << " Age:" << age << endl;}
public:string name;int age;
};//3. 成员函数和全局函数(Perosn对象相加)
Person PersonPlusPerson(Person& p1,Person& p2){string newname = p1.name + p2.name;int newage = p1.age + p2.age;Person newperson(newname,newage);return newperson;
}int main(){Person person("John",100);person.ShowPerson();cout << "---------" << endl;Person person1("John",20);Person person2("001", 10);//1.全局函数实现两个对象相加Person person3 = PersonPlusPerson(person1, person2);person1.ShowPerson();person2.ShowPerson();person3.ShowPerson();//2. 成员函数实现两个对象相加Person person4 = person1.PersonPlusPerson(person2);person4.ShowPerson();system("pause");return EXIT_SUCCESS;
}2.2.3 const修饰成员函数(常函数)
用const修饰的成员函数时,const修饰this指针指向的内存区域,成员函数体内不可以修改本类中的任何普通成员变量,
当成员变量类型符前用mutable修饰时例外。
//const修饰成员函数
class Person{
public:Person(){this->mAge = 0;this->mID = 0;}//在函数括号后面加上const,修饰成员变量不可修改,除了mutable变量void sonmeOperate() const{//this->mAge = 200; //mAge不可修改this->mID = 10; //const Person* const tihs;}void ShowPerson(){cout << "ID:" << mID << " mAge:" << mAge << endl;}
private:int mAge;mutable int mID;
};int main(){Person person;person.sonmeOperate();person.ShowPerson();system("pause");return EXIT_SUCCESS;
}2.2.4 const修饰对象(常对象)
常对象只能调用const的成员函数
常对象可访问 const 或非 const 数据成员,不能修改,除非成员用mutable修饰
class Person{
public:Person(){this->mAge = 0;this->mID = 0;}void ChangePerson() const{mAge = 100;mID = 100;}void ShowPerson(){cout << "ID:" << this->mID << " Age:" << this->mAge << endl;}public:int mAge;mutable int mID;
};void test(){ const Person person;//1. 可访问数据成员cout << "Age:" << person.mAge << endl;//person.mAge = 300; //不可修改person.mID = 1001; //但是可以修改mutable修饰的成员变量//2. 只能访问const修饰的函数//person.ShowPerson();person.ChangePerson();
}2.2.5 拓展
this指针指向的空间有没有存储静态成员变量?
没有
this指针的指向可以改变吗?
this指针的指向不能改变,也就是说this是Person *const this;
防止空指针调用成员函数
class Person{
public:Person(){this->mAge = 0;this->mID = 0;}void ShowPerson(){if(this == NULL){cout << "this==NULL" << endl;return;}cout << "ID:" << this->mID << " Age:" << this->mAge << endl;}public:int mAge;mutable int mID;
};void test(){ Person* person = NULL;person->ShowPerson();
}3. 友元
类的主要特点之一是数据隐藏,即类的私有成员无法在类的外部(作用域之外)访问。但是,有时候需要在类的外部访问类的私有成员,怎么办?
解决方法是使用友元函数,友元函数是一种特权函数,c++允许这个特权函数访问私有成员。这一点从现实生活中也可以很好的理解:
比如你的家,有客厅,有你的卧室,那么你的客厅是Public的,所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是呢,你也可以允许你的闺蜜好基友进去。
程序员可以把一个全局函数、某个类中的成员函数、甚至整个类声明为友元。
3.1 友元语法
friend关键字只出现在声明处
其他类、类成员函数、全局函数都可声明为友元
友元函数不是类的成员,不带this指针
友元函数可访问对象任意成员属性,包括私有属性
class Building;
//友元类
class MyFriend{
public://友元成员函数void LookAtBedRoom(Building& building);void PlayInBedRoom(Building& building);
};
class Building{//全局函数做友元函数friend void CleanBedRoom(Building& building);
#if 0//成员函数做友元函数friend void MyFriend::LookAtBedRoom(Building& building);friend void MyFriend::PlayInBedRoom(Building& building);
#else //友元类friend class MyFriend;
#endif
public:Building();
public:string mSittingRoom;
private:string mBedroom;
};void MyFriend::LookAtBedRoom(Building& building){cout << "我的朋友参观" << building.mBedroom << endl;
}
void MyFriend::PlayInBedRoom(Building& building){cout << "我的朋友玩耍在" << building.mBedroom << endl;
}//友元全局函数
void CleanBedRoom(Building& building){cout << "友元全局函数访问" << building.mBedroom << endl;
}Building::Building(){this->mSittingRoom = "客厅";this->mBedroom = "卧室";
}int main(){Building building;MyFriend myfriend;CleanBedRoom(building);myfriend.LookAtBedRoom(building);myfriend.PlayInBedRoom(building);system("pause");return EXIT_SUCCESS;
}友元类注意:
友元关系不能被继承。
友元关系是单向的,类A是类B的朋友,但类B不一定是类A的朋友。
友元关系不具有传递性。类B是类A的朋友,类C是类B的朋友,但类C不一定是类A的朋友。
思考: c++是纯面向对象的吗?
如果一个类被声明为friend,意味着它不是这个类的成员函数,却可以修改这个类的私有成员,而且必须列在类的定义中,因此他是一个特权函数。c++不是完全的面向对象语言,而只是一个混合产品。增加friend关键字只是用来解决一些实际问题,这也说明这种语言是不纯的。毕竟c++设计的目的是为了实用性,而不是追求理想的抽象。
--- Thinking in C++
3.2 案例
请编写电视机类,电视机有开机和关机状态,有音量,有频道,提供音量操作的方法,频道操作的方法。由于电视机只能逐一调整频道,不能指定频道,增加遥控类,遥控类除了拥有电视机已有的功能,再增加根据输入调台功能。
提示:遥控器类可作为电视机类的友元类。
class Remote;class Television{friend class Remote;
public:enum{ On,Off }; //电视状态enum{ minVol,maxVol = 100 }; //音量从0到100enum{ minChannel = 1,maxChannel = 255 }; //频道从1到255Television(){mState = Off;mVolume = minVol;mChannel = minChannel;}//打开电视机void OnOrOff(){this->mState = (this->mState == On ? Off : On);}//调高音量void VolumeUp(){if (this->mVolume >= maxVol){return;}this->mVolume++;}//调低音量void VolumeDown(){if (this->mVolume <= minVol){return;}this->mVolume--;}//更换电视频道void ChannelUp(){if (this->mChannel >= maxChannel){return;}this->mChannel++;}void ChannelDown(){if (this->mChannel <= minChannel){return;}this->mChannel--;}//展示当前电视状态信息void ShowTeleState(){cout << "开机状态:" << (mState == On ? "已开机" : "已关机") << endl;if (mState == On){cout << "当前音量:" << mVolume << endl;cout << "当前频道:" << mChannel << endl;}cout << "-------------" << endl;}
private:int mState; //电视状态,开机,还是关机int mVolume; //电视机音量int mChannel; //电视频道
};//电视机调台只能一个一个的调,遥控可以指定频道
//电视遥控器
class Remote{
public:Remote(Television* television){pTelevision = television;}
public:void OnOrOff(){pTelevision->OnOrOff();}//调高音量void VolumeUp(){pTelevision->VolumeUp();}//调低音量void VolumeDown(){pTelevision->VolumeDown();}//更换电视频道void ChannelUp(){pTelevision->ChannelUp();}void ChannelDown(){pTelevision->ChannelDown();}//设置频道 遥控新增功能void SetChannel(int channel){if (channel < Television::minChannel || channel > Television::maxChannel){return;}pTelevision->mChannel = channel;}//显示电视当前信息void ShowTeleState(){pTelevision->ShowTeleState();}
private:Television* pTelevision;
};//直接操作电视
void test01(){Television television;television.ShowTeleState();television.OnOrOff(); //开机television.VolumeUp(); //增加音量+1television.VolumeUp(); //增加音量+1television.VolumeUp(); //增加音量+1television.VolumeUp(); //增加音量+1television.ChannelUp(); //频道+1television.ChannelUp(); //频道+1television.ShowTeleState();
}//通过遥控操作电视
void test02(){//创建电视Television television;//创建遥控Remote remote(&television);remote.OnOrOff();remote.ChannelUp();//频道+1remote.ChannelUp();//频道+1remote.ChannelUp();//频道+1remote.VolumeUp();//音量+1remote.VolumeUp();//音量+1remote.VolumeUp();//音量+1remote.VolumeUp();//音量+1remote.ShowTeleState();
}4. 数组类封装
4.1 设计
目的:设计一个类,该类有数组的功能,可以存储数据,可以删除修改数据
设计核心数据:
属性:指针(指向堆区空间),数组实际存储的元素个数,数组容量
方法:构造(开辟堆区空间),尾插,头插,指定位置插入,尾删,头删,获取指定位置的值,指定位置修改值,获取数组元素个数,获取数组容量,析构函数
4.2 源码
MyArray.h
#ifndef MYARRAY_H
#define MYARRAY_Hclass MyArray{
public://无参构造函数,用户没有指定容量,则初始化为100MyArray();//有参构造函数,用户指定容量初始化explicit MyArray(int capacity);//用户操作接口//根据位置添加元素void SetData(int pos, int val);//获得指定位置数据int GetData(int pos);//尾插法void PushBack(int val);//获得长度int GetLength();//析构函数,释放数组空间~MyArray();
private:int mCapacity; //数组一共可容纳多少个元素int mSize; //当前有多少个元素int* pAdress; //指向存储数据的空间
};#endifMyArray.cpp
#include"MyArray.h"MyArray::MyArray(){this->mCapacity = 100;this->mSize = 0;//在堆开辟空间this->pAdress = new int[this->mCapacity];
}
//有参构造函数,用户指定容量初始化
MyArray::MyArray(int capacity){this->mCapacity = capacity;this->mSize = 0;//在堆开辟空间this->pAdress = new int[capacity];
}
//根据位置添加元素
void MyArray::SetData(int pos, int val){if (pos < 0 || pos > mCapacity - 1){return;}pAdress[pos] = val;
}
//获得指定位置数据
int MyArray::GetData(int pos){return pAdress[pos];
}
//尾插法
void MyArray::PushBack(int val){if (mSize >= mCapacity){return;}this->pAdress[mSize] = val;this->mSize++;
}
//获得长度
int MyArray::GetLength(){return this->mSize;
}
//析构函数,释放数组空间
MyArray::~MyArray(){if (this->pAdress != nullptr){delete[] this->pAdress;}
}TestMyArray.cpp
#include"MyArray.h"void test(){//创建数组MyArray myarray(50);//数组中插入元素for (int i = 0; i < 50; i++){//尾插法myarray.PushBack(i);//myarray.SetData(i, i);}//打印数组中元素for (int i = 0; i < myarray.GetLength(); i++){cout << myarray.GetData(i) << " ";}cout << endl;
}【上一篇】C++核心知识(二)—— 类和对象(类的封装)、对象的构造和析构(浅拷贝、深拷贝、explicit、动态分配内存)
相关文章:
C++核心知识(三)—— 静态成员(变量、函数、const成员)、面向对象模型(this指针、常函数、常对象)、友元、数组类、单例模式
【上一篇】C核心知识(二)—— 类和对象(类的封装)、对象的构造和析构(浅拷贝、深拷贝、explicit、动态分配内存)1. 静态成员在类定义中,它的成员(包括成员变量和成员函数),这些成员可以用关键字static声明为…...
RocketMQ【3】Rocketmq集群部署(多master多slave)异步复制
系列文章目录 RocketMQ【1】linux安装配置Rocketmq(单机版) RocketMQ【2】Rocketmq控制台安装启动(单机版) 文章目录系列文章目录一、异步复制的优缺点1、优点2、缺点二、架构1、架构图2、介绍3、机器配置三、配置1、master节点配…...
魏玛早春 木心
<font face“黑体” color#CD5C5C size6 魏玛早春 木心 温带每个季节之初 总有神圣气象恬漠地 剀切地透露在风中 冬天行将退尽 春寒嫩生生 料峭而滋润 漾起离合纷纷的私淑记忆 日复一日 默认季节的更替 以春的正式最为谨慎隆重 如果骤尔明暖 鸟雀疏狂飞鸣 必定会吝悔似的剧…...
关于Scipy的概念和使用方法及实战
关于scipy的概念和使用方法 什么是Scipy Scipy是一个基于Python的科学计算库,它提供了许多用于数学、科学、工程和技术计算的工具和函数。Scipy的名称是“Scientific Python”的缩写。 Scipy包含了许多子模块,其中一些主要的子模块包括: …...
第二章Linux操作语法1
文章目录vi和vim常用的三种模式vi和vim快捷键Linux开机,重启用户管理用户信息查询管理who和whoami用户组信息查询管理用户和组的相关文件实用指令集合运行级别帮助指令manhelp文件管理类pwd命令ls命令cd命令mkdir命令rmdir命令rm命令touch命令cp指令mv指令文件查看类…...
linux内核调度问题分析
目录 一、调度场景分析 不支持内核抢占的内核 支持内核抢占 二、如何让新进程执行 三、调度的本质 一、调度场景分析 假如内核只有3个线程,线程0创建线程1和线程2.当系统时钟到来时,时钟中断处理函数会检查是否有进程需要调度。当有进程需要调度时…...
C语言-基础了解-25-C强制类型转换
C强制类型转换 一、强制类型转换 强制类型转换是把变量从一种类型转换为另一种数据类型。例如,如果您想存储一个 long 类型的值到一个简单的整型中,您需要把 long 类型强制转换为 int 类型。您可以使用强制类型转换运算符来把值显式地从一种类型转换为…...
【Python】如何安装 Allure 工具进行自动化测试
Allure 是一种流行的工具,用于以人类可读的格式生成测试报告,从而更容易理解和分析测试结果。在这篇博客中,我们将探索如何在 Windows 机器上安装 Allure 及其依赖项。 1 Prerequisites 先决条件 在田辛老师开始之前,请确保您的…...
nginx七大核心应用场景详解 解决生产中的实际问题 二次开发扩展
nginx七大核心应用场景详解 & 解决生产中的实际问题1、nginx的安装与简单配置1.1、环境准备1.2、nginx基本操作指令:1.3、安装成系统服务1.4、conf 配置文件说明2、虚拟主机2.1、nginx多主机配置2.2、二级域名与短网址解析3、基于反向代理的负载均衡3.1、跳转到…...
Java 整合 Redis
文章目录Java 整合 Redis一、Jedis二、Spring-Data-RedisJava 整合 Redis Redis 在项目中我们主要用来做缓存,就像我们用 MySQL 做持久层数据一样。Redis 的客户端有两种实现方式: 一是直接调用 Jedis 来实现,类似于 Java 使用 JDBC 操作数…...
Django实践-03模型-02基于admin管理表
文章目录Django实践-03模型利用Django后台管理模型1. 将admin应用所需的表迁移到数据库中。2. 创建访问admin应用的超级用户账号,3. 运行项目4.注册模型类5.对模型进行CRUD操作。6.实现学科页和老师页效果1. 修改polls/views.py文件。2.修改templates/polls/subject…...
如何安装python
windows安装 下载安装包 登录python官网 https://www.python.org/ 点击downloads 置顶下载的是最新的python版本 如果想下载指定版本往下翻找 安装程序 点击即可下载,然后打开下载的exe程序 勾选添加pythonexec到path,也就是添加到环境变量 使用a…...
java String类 万字详解(通俗易懂)
目录 一、前言 二、介绍和溯源 三、String类常用构造器 1.String() 2.String(byte[] bytes) 3.String(char[] value) 4.String(char[] value, int offset, int count) 5.String(String original) Δ演示 : 四、不同方式创建String类对象的区别 1.直接赋值的方式 2.常规new…...
Hive拉链表
概述 拉链表:维护历史状态以及最新状态数据的表 作用场景 1. 数据量比较大。 2. 表中的部分字段会被更新,比如用户的地址,银行利率,订单的状态等。 3. 需要查看某一个时间点或者时间段的历史快照信息,比如,…...
day1 开发我的第一个MyBatis程序
文章目录开发我的第一个MyBatis程序1. resources目录:2. 开发步骤3. 从 XML 中构建 SqlSessionFactoryMyBatisIntroductionTest4. mybatis中有两个主要的配置文件:5. 关于第一个程序的小细节mybatis-config.xml6. 关于mybatis的事务管理机制。࿰…...
【CDP】更改solr 存储路径导致ranger-audit 大量报错问题解决
前言 我们生产上公司是使用的CDP集群,一次管理员通知,Solr 组件的数据存放路径磁盘空间不够。 我们的solr 组件时为 Ranger 服务提供日志审计功能, 在我们更改了磁盘路径,并重启了Solr 组件,然后发现相关组件&#…...
JavaScript基础一、简介
零、文章目录 文章地址 个人博客-CSDN地址:https://blog.csdn.net/liyou123456789个人博客-GiteePages:https://bluecusliyou.gitee.io/techlearn 代码仓库地址 Gitee:https://gitee.com/bluecusliyou/TechLearnGithub:https:…...
Qt音视频开发20-vlc内核动态保存录像文件(不需要重新编译源码)
一、前言 在vlc默认提供的保存文件方式中,通过打开的时候传入指定的参数来保存文件,直到关闭播放生成文件,这种方式简单暴力,但是不适用大部分的场景,大部分时候需要的是提供开始录制和停止录制的功能,也就…...
【深度学习】BERT变体—RoBERTa
RoBERTa是的BERT的常用变体,出自Facebook的RoBERTa: A Robustly Optimized BERT Pretraining Approach。来自Facebook的作者根据BERT训练不足的缺点提出了更有效的预训练方法,并发布了具有更强鲁棒性的BERT:RoBERTa。 RoBERTa通过以下四个方面…...
java面试准备1
JVM、JRE和JDK的关系 JVM:Java Virtual Machine是java虚拟机,Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此java可以实现跨平台使用。 JRE:Java Runtion Envirement包括Java虚拟机和Java程序所需要的核心类库等。 J…...
网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
UDP(Echoserver)
网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法:netstat [选项] 功能:查看网络状态 常用选项: n 拒绝显示别名&#…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)
推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
Qemu arm操作系统开发环境
使用qemu虚拟arm硬件比较合适。 步骤如下: 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载,下载地址:https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...
