【C++】详细介绍类的相关语法概念,this,默认成员函数,static,友元,内部类

目录

1. 类的基本概念

1.1 类的语法

1.2 类的访问限定符

1.3 类的两种定义方式

1.4 类的作用域

1.5 类的实例化

1.6 类对象的大小

2. this指针

2.1 概念

2.2 特性

2.3 面试题

3. 类的六个默认成员函数

3.1 构造函数

3.1.1 特性

3.1.2 默认构造函数 

3.1.3 函数体内赋值

3.1.4 初始化列表

3.1.5 explicit关键字

3.2 析构函数

3.3 拷贝构造

3.4 赋值重载

3.4.1 运算符重载

3.4.2 赋值运算符重载

3.5 const成员

3.6 取地址操作符重载及const取地址操作符重载

4. static 成员

4.1 概念

4.2 面试题

5. 友元

5.1 友元函数

5.2 友元类

6. 内部类

7. 日期类的实现

7.1 默认成员函数

7.2 比较函数 

7.5 运算函数

7.5.1 +=,+,-=,-

7.5.2 ++,--

7.5.3 流插入,流提取重载


1. 类的基本概念

1.1 类的语法

class className
{// 类体:由成员函数和成员变量组成
};  // 一定要注意后面的分号

class为定义类的关键字,ClassName为类的名字,{ }中为类的主体,注意类定义结束时后面分号不能省略。

类体中的内容称为类的成员,类中的变量称为类的属性或成员变量,类中的函数称为类的方法或者成员函数。

1.2 类的访问限定符

 

1. public修饰的成员在类外可以直接被访问。

2. protected和private修饰的成员在类外不能直接被访问。

3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。

4. 如果后面没有访问限定符,作用域就到 } 即类结束。

5. class的默认访问权限为private,struct为public(因为struct要兼容C)。

6. 访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别。


面试题:C++中struct和class的区别是什么?

C++需要兼容C语言,所以C++中struct可以当成结构体使用。另外C++中struct还可以用来定义类。和class定义类是一样的,区别是struct定义的类默认访问权限是public,class定义的类 默认访问权限是private。

1.3 类的两种定义方式

1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。


2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::。

1.4 类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。

在类体外定义成员时,需要使用 :: 作用域操作符指明成员属于哪个类域。

class Person
{
public:void PrintPersonInfo();
private:char _name[20];char _gender[3];int  _age;
};// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{cout << _name << " "<< _gender << " " << _age << endl;
}

1.5 类的实例化

用类类型创建对象的过程,称为类的实例化

1. 类是对对象进行描述的,是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它。

2. 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量。


 Person类是没有空间的,只有Person类实例化出的对象才有具体的数据。

1.6 类对象的大小

类对象的存储方式 :

类对象只保存成员变量,成员函数存放在公共的代码段。


实例:

// 类中既有成员变量,又有成员函数
class A1 {
public:void f1(){}
private:char _c;int _a;
};// 类中仅有成员函数
class A2 {
public:void f2() {}
};// 类中什么都没有---空类
class A3
{};

sizeof(A1) : __8___   sizeof(A2) : __1____    sizeof(A3) : __1____

结论:

1. 一个类的大小,实际就是该类中”成员变量”之和,当然要注意内存对齐。

2. 注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。分配一个字节,不存储数据,只是占位,表示对象存在过。


2. this指针

2.1 概念

 日期类

class Date
{ 
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;     int _month;    int _day;      
};int main()
{Date d1, d2;d1.Init(2022,1,11);d2.Init(2022, 1, 12);return 0;
}

C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过该指针去访问。只不过所有的操作用户是看不到的,即用户不需要来传递,编译器自动完成。

实际上:

this在实参和形参位置不能显示写,但可以在类里显示用。

2.2 特性

1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。

2. 只能在“成员函数”的内部使用

3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给 this形参。所以对象中不存储this指针。

4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传 递,不需要用户传递。

2.3 面试题

1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

class A
{
public:void Print(){cout << "Print()" << endl;}private:int _a;
};int main()
{A* p = nullptr;p->Print();return 0;
}

答:C

解析:因为成员函数在公共代码段,不需要解引用。

2.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

class A
{ 
public:void PrintA() {cout<<_a<<endl;}private:int _a;
};int main()
{A* p = nullptr;p->PrintA();return 0;
}

答:B

解析:这里会用到this->_a,但传入的this是nullptr。

3. this指针存在哪里? 

答:this是一个形参,一般是存在栈帧里,也就是栈里。

4. this指针可以为空吗?

答:可以。


3. 类的六个默认成员函数

如果一个类中什么成员都没有,简称为空类。

空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。

默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

3.1 构造函数

3.1.1 特性

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。

其特征如下:

1. 函数名与类名相同。

2. 无返回值。

3. 对象实例化时编译器自动调用对应的构造函数。

4. 构造函数可以重载。

5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数。

class Date{public:// 1.无参构造函数Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};void TestDate(){Date d1; // 调用无参构造函数Date d2(2015, 1, 1); // 调用带参的构造函数// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明Date d3(); //这是错的}

3.1.2 默认构造函数 

无参的构造函数全缺省的构造函数以及我们没写编译器默认生成的构造函数都称为默认构造函数(不传参就可以调用的),并且默认构造函数只能有一个。

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
};

编译器默认生成的构造函数的特点:

1. 我们不写就会生成,写了就不生成。

2. 内置类型成员不会处理。

3. 自定义类型成员才处理,会去调用这个成员的构造函数。

解释:C++把类型分成内置类型(基本类型)和自定义类型。

内置类型就是语言提供的数据类型,如:int/char...,指针也是内置类型。

自定义类型就是我们使用class/struct/union等自己定义的类型。

class Time
{
public:Time(){...}private:...
};class Date
{
private:// 基本类型(内置类型)int _year;int _month;int _day;// 自定义类型Time _t;
};int main()
{Date d;return 0;
}

注意:C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在 类中声明时可以给默认值。

class Date
{
private:// 基本类型(内置类型)int _year = 1970; //声明给的是缺省值。int _month = 1;int _day = 1;// 自定义类型Time _t;
};

3.1.3 函数体内赋值

在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。

class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
};

虽然上述构造函数调用之后,对象中的成员变量已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值。

3.1.4 初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。

class Date
{
public://初始化列表是每个成员定义的地方。Date(int year, int month, int day): _year(year), _month(month), _day(day){}private://这里是每个成员声明的地方。int _year = 1; //这里给的是缺省值,这个缺省值是给初始化列表看的。int _month;int _day;
};

【注意】

1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)。

2. 引用成员变量,const成员变量,没有默认构造的自定义类型成员,必须放在初始化列表位置进行初始化。

3. 每个成员都会走初始化列表,如果你不给值初始化,那么内置类型就用随机值,自定义类型就调用自己的默认构造。

4. 成员变量在初始化列表中的初始化顺序是按照成员变量的声明顺序,与其在初始化列表中的先后次序无关。

3.1.5 explicit关键字

构造函数不仅可以构造与初始化对象,对于接收单个参数的构造函数,还具有类型转换的作用。

符合单个参数的构造函数有:

1. 构造函数只有一个参数,

2. 构造函数有多个参数,除第一个参数没有默认值外,其余参数都有默认值,

3. 全缺省构造函数。

class Date
{
public:Date(int year):_year(year){}...private:int _year;int _month;int _day;
};void Test()
{Date d1(2022);d1 = 2023; 
}

 用一个整形变量给日期类型对象赋值,实际编译器背后会用2023构造一个匿名对象,最后用匿名对象调用赋值重载给d1对象进行赋值。

如果你不想要这种隐式类型转换,你可以在构造函数前面加ecplicit。


3.2 析构函数

析构函数:对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

析构函数是特殊的成员函数,其特征如下:

1. 析构函数名是在类名前加上字符 ~。

2. 无参数无返回值类型,所以析构函数不能重载。

3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认析构函数。

4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

5. 编译器生成的默认析构函数,会调用自定义类型成员的析构函数。

class Time
{
public:~Time(){cout << "~Time()" << endl;}private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};int main()
{Date d;return 0;
}

程序运行结束后输出:~Time()

在main方法中根本没有直接创建Time类的对象,为什么最后会调用Time类的析构函数?

因为:main方法中创建了Date对象d,而d中包含4个成员变量,其中_year, _month, _day三个是内置类型成员,销毁时不需要资源清理,最后系统直接将其内存回收即可;

而_t是Time类对象,所以在d销毁时,要将其内部包含的Time类的_t对象销毁,所以要调用Time类的析构函数。

但是: main函数中不能直接调用Time类的析构函数,实际要释放的是Date类对象,所以编译器会调用Date类的析构函数,而Date没有显式提供,则编译器会给Date类生成一个默认析构函数,目的是在其内部调用Time类的析构函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁

main函数中并没有直接调用Time类析构函数,而是显式调用编译器为Date类生成的默认析 构函数 

3.3 拷贝构造

拷贝构造函数也是特殊的成员函数,其特征如下:

1. 拷贝构造函数是构造函数的一个重载形式。

2. 拷贝构造函数的参数只有一个且必须是同类类型对象的引用,const修饰,不能使用传值传参,因为将参数传给形参本身也是一个拷贝构造,会不断调用没有尽头。

3. 若未显式定义,编译器会生成默认的拷贝构造函数。在编译器生成的默认拷贝构造函数中,内置类型是按照字节方式直接拷贝的,而自定义类型是调用它自己的拷贝构造函数完成拷贝的。

class Date
{
public:...//拷贝构造函数Date(const Date& d)   {_year = d._year;_month = d._month;_day = d._day;}private:int _year;int _month;int _day;
};int main()
{Date d1;Date d2(d1);return 0;
}

浅拷贝与深拷贝:

默认生成的拷贝构造函数只能实现浅拷贝,有些情况我们需要自己显示实现来完成深拷贝。

比如有些成员变量是指针指向一些在堆上的空间,如果你只是浅拷贝就只能拷贝地址,会出现两个对象他们的成员变量都指向同一个空间,析构时就会出现意外。

注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请 时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

3.4 赋值重载

3.4.1 运算符重载

函数名字为:关键字operator后面接需要重载的运算符符号。

函数原型:返回值类型 operator操作符(参数列表)

注意:

1. 不能创建新的操作符:比如operator@。

2. 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this。

3. “ .* ”,“ :: ”,“ sizeof ”,“ ?:(三目) ”,“ . ” 注意以上5个运算符不能重载。

class Date
{ 
public:...    bool operator==(const Date& d2){return _year == d2._year;&& _month == d2._month&& _day == d2._day;}private:int _year;int _month;int _day;
};

d1 == d2 相当于 d1.operator(d2)。

3.4.2 赋值运算符重载

赋值运算符重载格式:

1. 参数类型:const 同类类型&,传递引用可以提高传参效率。

2. 返回值类型:同类类型&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值,返回*this :要复合连续赋值的含义。

3. 检测是否自己给自己赋值。

class Date
{ 
public :...Date& operator=(const Date& d){if(this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}private:int _year ;int _month ;int _day ;
};

赋值运算符只能重载成类的成员函数不能重载成全局函数

原因:赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。


用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝。

注意1:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用它自己的赋值运算符重载完成赋值。

注意2:如果类中未涉及到资源管理,赋值运算符是否实现都可以;一旦涉及到资源管理则必 须要实现。以满足深拷贝,如果有成员指向其他空间,那么不是拷贝这个空间的地址,而是把这个空间的内容拷贝到我的自己开的空间。

3.5 const成员

将const修饰的“成员函数”称之为const成员函数。

const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

class Date
{
public:...void Print(){...}void Print() const{...}private:int _year; int _month; int _day; 
};void Test()
{Date d1(2022,1,13);d1.Print();const Date d2(2022,1,13);d2.Print();
}

请思考下面的几个问题:

1. const对象可以调用非const成员函数吗? 答:不行,这是权限放大。

2. 非const对象可以调用const成员函数吗? 答:可以,这是权限缩小。

3. const成员函数内可以调用其它的非const成员函数吗?答:不行。

4. 非const成员函数内可以调用其它的const成员函数吗?答:可以。

3.6 取地址操作符重载及const取地址操作符重载

class Date
{ 
public :...Date* operator&(){return this ;}const Date* operator&() const{return this ;}private :int _year; int _month; int _day; 
};

这两个运算符一般不需要自己写,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!      


4. static 成员

4.1 概念

用static修饰的成员变量,称之为静态成员变量。

用static修饰的成员函数,称之为静态成员函数。

静态成员变量一定要在类外进行初始化。


【特性】

1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区。

2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明。

3. 类静态成员可用 类名::静态成员 或者 对象.静态成员 来访问。

4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员。

5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制。

6. 静态成员变量不会走初始化列表,声明的时候不用给缺省值。


【问题】

1. 静态成员函数可以调用非静态成员函数吗?答:不能。

2. 非静态成员函数可以调用类的静态成员函数吗?答:能。

4.2 面试题

实现一个类,计算程序中创建出了多少个类对象。 

class A
{
public:A() { ++_scount; }A(const A& t) { ++_scount; }~A() { --_scount; }static int GetACount() { return _scount; } //静态成员函数。private:static int _scount; //静态成员变量声明。
};int A::_scount = 0; //静态成员变量类外定义。void TestA()
{cout << A::GetACount() << endl; //静态成员函数的用法。A a1, a2;A a3(a1);cout << A::GetACount() << endl;
}

5. 友元

5.1 友元函数

友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。

class Date
{friend ostream& operator<<(ostream& _cout, const Date& d);public:Date(int year = 1900, int month = 1, int day = 1){...}private:int _year;int _month;int _day;
};ostream& operator<<(ostream& _cout, const Date& d)
{_cout << d._year << "-" << d._month << "-" << d._day;return _cout;
}int main()
{Date d;cout << d << endl;return 0;
}

【说明】

1. 友元函数可访问类的私有和保护成员,但不是类的成员函数。

2. 友元函数可以在类域的任何地方声明,不受类访问限定符限制。

3. 一个函数可以是多个类的友元函数。

5.2 友元类

1. 友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的私有或保护成员。

2. 友元关系是单向的,不具有交换性。

3. 友元关系不能传递。

4. 友元关系不能继承。

class Time
{// 声明日期类为时间类的友元类,则在日期类中就直接访问时间类中的私有成员变量。friend class Date; public:...private:int _hour;int _minute;int _second;
};class Date
{
public:...void SetTimeOfDate(int hour, int minute, int second){// 直接访问时间类私有的成员变量_t._hour = hour;_t._minute = minute;_t._second = second;}private:int _year;int _month;int _day;Time _t; //时间类类型
};

6. 内部类

【概念】

如果一个类定义在另一个类的内部,这个类就叫做内部类。

内部类是一个独立的类,它不属于外部类,它只是受外部类的类域和访问限定符的限制。

【注意】

内部类是外部类的友元类,内部类可以访问外部类的所有成员,但是外部类不能,因为外部类不是内部类的友元。

【特性】

1. 内部类可以定义在外部类的public、protected、private都是可以的。

2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。

3. sizeof(外部类)=外部类,和内部类没有任何关系。

class A
{
private:static int k;int h;public:class B {public:void foo(const A& a){cout << k << endl;cout << a.h << endl;}};
};int A::k = 1;int main()
{A::B b; //受A的类域限制。return 0;
}

7. 日期类的实现

7.1 默认成员函数

class Date
{
public://构造Date(int year = 1900, int mouth = 1, int day = 1):_year(year),_mouth(mouth),_day(day){}//拷贝构造Date(const Date& d){_year = d._year;_mouth = d._mouth;_day = d._day;}//赋值重载Date& operator=(const Date& d){if (&d != this){_year = d._year;_mouth = d._mouth;_day = d._day;}return *this;}private:int _year;int _mouth;int _day;
};

赋值重载有两点注意,第一不和自己赋值,第二要符合连续赋值。

7.2 比较函数 

先写小于和等于,后面都可以复用。

bool Date::operator<(const Date& d)
{if (_year < d._year){return true;}else if (_year == d._year && _mouth < d._mouth){return true;}else if (_year == d._year && _mouth == d._mouth && _day < d._day){return true;}else{return false;}
}bool Date::operator==(const Date& d)
{return _year == d._year && _mouth == d._mouth && _day == d._day;
}bool Date::operator<=(const Date& d)
{return *this < d || *this == d;
}bool Date::operator>(const Date& d)
{return !(*this <= d);	
}bool Date::operator>=(const Date& d)
{return !(*this < d);
}bool Date::operator!=(const Date& d)
{return !(*this == d);
}

7.5 运算函数

7.5.1 +=,+,-=,-

日期+=天数,日期+天数,日期-=天数,日期-天数

先写+=,再用+复用+=。

//获取不同月份的天数
int GetMouthDay(int year, int mouth)
{//提前准备数组保存每月的天数。static int mouth_day[] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };//2月需要特殊处理,4年1润并百年不润或400年1润。if (mouth == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)){return 29;}return mouth_day[mouth];
}Date& Date::operator+=(int day)
{_day += day;//当天数超出范围就需要不断处理。while (_day > GetMouthDay(_year, _mouth)){//天满月进位。_day -= GetMouthDay(_year, _mouth);++_mouth;//月满年进位。if (_mouth == 13){++_year;_mouth = 1;}}return *this;
}Date Date::operator+(int day)
{//拷贝构造一个临时对象。Date tmp(*this);tmp += day;return tmp;
}Date& Date::operator-=(int day)
{_day -= day;//如果天数小于1就要借位。while (_day <= 0){--_mouth;//月份借完了就找年借。if (_mouth == 0){--_year;_mouth = 12;}_day += GetMouthDay(_year, _mouth);}return *this;
}Date Date::operator-(int day)
{Date tmp(*this);tmp -= day;return tmp;
}

日期-日期,返回天数。

int Date::operator-(const Date& d)
{//如果前面大于后面那么结果是正的,否则是负的。Date max = *this;Date min = d;int ret = 1;if (*this < d){max = d;min = *this;ret = -1;}//算出它们之间的差距,再乘上正负号。int n = 0;while (min != max){++min;++n;}return n * ret;
}

7.5.2 ++,--

C++规定:

后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递 

通过复用+=,-=实现。

Date& Date::operator++()
{return *this += 1;
}Date Date::operator++(int)
{Date tmp(*this);*this += 1;return tmp;
}Date& Date::operator--()
{return *this -= 1;
}Date Date::operator--(int)
{Date tmp(*this);*this -= 1;return tmp;
}

7.5.3 流插入,流提取重载

1. 它们需要友元声明,因为要访问私有成员变量。

2. 从左到右结算的。

ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "/" << d._mouth << "/" << d._day << endl;return out;
}istream& operator>>(istream& in, const Date& d)
{in >> d._year >> d._mouth >> d._day;return in;
}

Date/Date · 林宇恒/code-cpp - 码云 - 开源中国 (gitee.com)

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

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

相关文章

高效数据移动指南 | 如何快速实现数据库 MySQL 到 MongoDB 的数据同步?

在现代企业中&#xff0c;数据无处不在&#xff0c;贯穿于各个业务环节和系统之间。无论是跨系统的数据集成、多地域的数据协同&#xff0c;还是实时应用的数据同步&#xff0c;数据的一致性和及时性都至关重要。在数字化转型的过程中&#xff0c;如何确保不同系统、地域、设备…

OCR2.0--General OCR Theory

引领光学字符识别&#xff08;OCR&#xff09;的新篇章 引言&#xff1a;OCR技术进化的必要性 光学字符识别&#xff08;OCR&#xff09;是一项广泛应用的技术&#xff0c;它能够从图像中提取字符并将其转换为可编辑格式。虽然OCR-1.0在过去取得了广泛应用&#xff0c;但传统…

水滴式多功能粉碎机:粉碎中草药的好帮手

水滴式中草药粉碎机&#xff0c;顾名思义&#xff0c;其设计灵感源自自然界中水滴的柔和与力量。它摒弃了传统粉碎机粗犷的粉碎方式&#xff0c;采用低速研磨技术&#xff0c;模拟水滴穿透岩石的细腻与持久&#xff0c;对中草药进行温和而深入的粉碎。这种技术不仅保留了药材中…

Redis集群_cluster

cluster集群 cluster翻译就是集群&#xff0c;所以cluster集群也叫做redis集群相比于哨兵模式&#xff0c;cluster集群能支持扩容&#xff0c;并且无需额外的节点来监控状态&#xff0c;所以使用这种模式集群的系统会用的更多些redis cluster采用的是去中心化网络拓扑架构&…

2024.9.14(RC和RS)

一、replicationcontroller &#xff08;RC&#xff09; 1、更改镜像站 [rootk8s-master ~]# vim /etc/docker/daemon.json {"registry-mirrors": ["https://do.nark.eu.org","https://dc.j8.work","https://docker.m.daocloud.io",&…

探索UWB技术的独特优势:实现高精度定位

UWB定位技术是一种利用无线信号进行精确位置定位的技术&#xff0c;它利用超宽带无线电信号通过测量信号的到达时间、相位差和信号能量等参数来确定物体的精确位置。 UWB定位技术具有多种优势&#xff0c;首先&#xff0c;它具有较高的定位精度&#xff0c;可实现毫米级的精确…

哈工大“计算机设计与实践”(cpu)处理器实验设计报告

哈工大“计算机设计与实践”&#xff08;cpu&#xff09;处理器实验设计报告 【哈工大“计算机设计与实践”&#xff08;cpu&#xff09;处理器实验设计报告】 在计算机科学领域&#xff0c;CPU&#xff08;中央处理器&#xff09;是计算机系统的核心部件&#xff0c;负责执行指…

性能诊断的方法(四):自下而上的资源诊断方法和发散的异常信息诊断方法

关于性能诊断的方法&#xff0c;我们可以按照“问题现象—直接原因—问题根源”这样一个思路去归纳。我们先从问题的现象去入手&#xff0c;包括时间的分析、资源的分析和异常信息的分析。接下来再去分析产生问题现象的直接原因是什么&#xff0c;这里我们归纳了自上而下的资源…

C语言 13 指针

指针可以说是整个 C 语言中最难以理解的部分了。 什么是指针 还记得在前面谈到的通过函数交换两个变量的值吗&#xff1f; #include <stdio.h>void swap(int, int);int main() {int a 10, b 20;swap(a, b);printf("a %d, b %d", a, b); }void swap(int …

Python编码系列—Python建造者模式:构建复杂对象的优雅之道

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

传知代码-融合经典与创新的图像分类新途径

代码以及视频讲解 本文所涉及所有资源均在传知代码平台可获取 概述 在当前的深度学习领域&#xff0c;构建兼具高性能与灵活性的卷积神经网络&#xff08;CNN&#xff09;已成为计算机视觉研究的核心课题。本文介绍了一种全新的卷积神经网络架构&#xff0c;该网络巧妙地结合…

OZON电子产品大幅增长,OZON跨境PS5销量激增

Top1 存储卡 Карта памяти Canvas Select Plus 128 ГБ 商品id&#xff1a;1548303593 月销量&#xff1a;2131 欢迎各位卖家朋友点击这里&#xff1a; &#x1f449; D。DDqbt。COm/74rD 免费体验 随着智能手机和平板电脑的普及&#xff0c;用户对于存储空…

vite + vue3 + ts 移动端开箱即用现代开发模板

中文 | English SouthernWind https://blog.csdn.net/nanchen_J?typeblog sw-template vite vue3 ts 移动端开箱即用现代开发模板 特点 &#x1f436; Vite 的Vue3 的文件路由布局系统Mock 后续支持Api 自动引入组件自动引入VueUse 支持TypeScript 的Tailwind css 的暗…

Gitlab实现多项目触发式自动CICD

工作中可能会遇到这种场景&#xff0c;存在上游项目A和下游项目B&#xff0c;项目B的功能依赖项目A&#xff08;比如B负责日志解析&#xff0c;A是日志描述语言代码&#xff09;&#xff0c;这种相互依赖的项目更新流程一般如下&#xff1a; A项目更新&#xff0c;通知B项目开发…

好用的电脑监控软件推荐!分享六个企业必备的电脑监控软件,赶紧Get吧!

数字化办公日益普及&#xff0c;由于工作的需要&#xff0c;几乎每个员工都有自己的电脑&#xff0c;并且大多数电脑都接入了互联网。 这使得电脑监控软件&#xff0c;变为企业管理中必不可少的一部分&#xff01;它们不仅能够帮助管理者实时了解员工的工作状态&#xff0c;提…

充电宝什么品牌比较好用?2024年最值得推荐充电宝品牌!

近年来&#xff0c;随着电子设备使用需求的增加&#xff0c;充电宝市场呈现出蓬勃发展的态势。优秀的充电宝产品不仅能够提供稳定的充电速度&#xff0c;还具备方便携带的体验&#xff0c;深受用户喜爱。然而&#xff0c;面对市场上众多品牌和型号的选择&#xff0c;如何找到最…

Linux云计算 |【第二阶段】SHELL-DAY5

主要内容&#xff1a; awk命令、内置变量&#xff08;FS、$0、$1、$2、NF、NR&#xff09;、过滤时机&#xff08;BEGIN{}、{}、END{}&#xff09;、处理条件&#xff08;正则、&&、||、~\!~、等&#xff09;、awk数组、监控脚本、安全检测脚本 一、awk介绍 awk 是一…

基于微信平台的旅游出行必备商城小程序+ssm(lw+演示+源码+运行)

摘 要 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…

影视直冲?对接卡券特权充值接口对于用户来说有什么优势?

对用户来说有哪些优势&#xff1a; 便利性&#xff1a;用户可以直接在应用程序或网站上充值和使用卡券&#xff0c;无需通过多个平台或渠道&#xff0c;提高了用户体验。实时性&#xff1a;卡券充值和使用状态可以实时更新&#xff0c;用户可以立即看到余额变化和卡券状态。安…

移动硬盘无法读取?别慌!这些方法助你恢复数据!

在我们的日常工作和生活中&#xff0c;移动硬盘作为重要的数据存储工具&#xff0c;承载着珍贵资料。然而&#xff0c;移动硬盘无法被电脑读取的情况时有发生&#xff0c;令人焦急。别慌&#xff0c;下面为大家详细介绍恢复移动硬盘数据的有效方法。 一、检查硬件连接和驱动问题…