当前位置: 首页 > news >正文

C++类与对象基础探秘系列(二)

目录

类的6个默认成员函数

构造函数

  构造函数的概念

  构造函数的特性

析构函数

  析构函数的概念

  析构函数的特性

拷贝构造函数

  拷贝构造函数的概念

  拷贝构造函数的特性

赋值运算符重载

  运算符重载

  赋值运算符重载

const成员

  const修饰类的成员函数

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


类的6个默认成员函数

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

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

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

注意:这些默认成员函数如果未被显式定义,编译器会自动生成。 

构造函数

        构造函数是C++编程语言中一个特殊类型的方法,其主要目的是在创建类的新对象时初始化该对象的成员变量。

  构造函数的概念

        概念:名字与类名相同,创建类类型对象时由编译器自动调用,保证每个数据成员都有 一个合适的初始值,并且在对象的生命周期内只调用一次。

例如,以下日期类中的成员函数Date就是一个构造函数。当你用该日期类创建一个对象时,编译器会自动调用该构造函数对新创建的变量进行初始化。 

class Date
{
public:Date(int year = 1, int month = 1, int day = 1) // 构造函数{_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};

注意:构造函数的主要职责是初始化对象不是开辟空间创建对象。 

  构造函数的特性

1、构造函数的函数名与类名相同。

2、构造函数无返回值。

        无返回值是真的无返回值,而不是说返回值为void。

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

        当用类创建一个对象时,编译器会自动调用该类的构造函数对新创建的变量进行初始化。

4、构造函数支持重载。

       意味着可以有多种初始化对象的方式,编译器会根据所传递的参数去调用对应的构造函数。

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(); 声明了d3函数,该函数无参,返回一个日期类型的对象

5、无参的构造函数、全缺省的构造函数以及我们不写编译器自动生成的构造函数都称为默认构造函数,并且默认构造函数只能有一个。

        初学C++时,可能认为只有当我们不写,编译器自动生成的构造函数才被称为默认构造函数。其实并不是这样的,以下3种都叫做默认构造函数:

  •         我们不写,编译器自动生成的构造函数。
  •         我们自己写的无参的构造函数。
  •         我们自己写的全缺省的构造函数。

总结:涉及到不接受参数的构造函数,都可以视作“默认构造函数”的范畴。

6、如果类中没有显示定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,若用户显示定义了,则编译器就不再生成。

        那么既然在我们不写的情况下,编译器会自动生成一个构造函数,那我们是不是就没有必要自己写构造函数了?

#include <iostream>using namespace std;class Date
{
public:void Print(){cout << _year << "年 " << _month << "月 " << _day << "日 " << endl;}
private:int _year;int _month;int _day;
};int main()
{Date d1; // 编译器将调用自动生成的默认构造函数对d1进行初始化d1.Print();return 0;
}

代码结果:

        d1对象调用了编译器自动生成的构造函数后,d1对象的_year/_month/_day依旧是随机值,那这编译器自动生成的构造函数还有什么意义?

7、编译器生成默认的构造函数会对自定类型成员调用的它的默认成员函数。

编译器自动生成的构造函数机制:
        1、编译器自动生成的构造函数对内置类型不做处理。
        2、对于自定义类型,编译器会再去调用它们自己的默认构造函数。

        C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语言提供的数据类型,如:int/char...,自定义类型就是我们使用class/struct/union等自己定义的类型。看看下面的程序

#include <iostream>using namespace std;class Time
{
public:Time(){cout << "Time()" << endl; // 查看是否进入该构造函数_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year;int _month;int _day;// 自定义类型Time _t;
};int main()
{Date d;return 0;
}

代码结果:

 总结:尽管C++编译器会自动生成默认构造函数,但往往我们需自定义构造函数达到我们想要的效果

析构函数

  析构函数的概念

        概念:与构造函数功能相反,析构函数负责完成对象的销毁,对象在销毁时会自动调用析构函数,完成类的一些资源清理工作。

        我们知道当一个类对象销毁时,其中的局部变量也会随着该对象的销毁而销毁,例如,我们用日期类创建了一个对象d1,当d1被销毁时,对象d1当中的局部变量_year/_month/_day也会被编译器销毁。

        但是这并不意味着析构函数没有什么意义。像栈(Stack)这样的类对象,当该对象被销毁时,其中动态开辟的栈并不会随之被销毁,需要我们对其进行空间释放,这时析构函数的意义就体现了。

  析构函数的特性

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

class Date
{
public:Date() // 构造函数{}~Date() // 析构函数{}
private:int _year;int _month;int _day;
};

2. 无参数无返回值类型。

        无返回值也是真的无返回值,而不是返回值为void。

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

        析构函数不能重载。

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

#include <iostream>using namespace std;class MyClass {
public:// 构造函数MyClass() {cout << "构造函数被调用,对象创建了。" << endl;}// 析构函数~MyClass() {cout << "析构函数被调用,对象将被销毁。" << endl;}
};int main() 
{// 创建一个MyClass类型的局部对象MyClass obj;// 当obj的作用域结束时(这里是大括号结束),析构函数会被自动调用// 这里obj对象生命周期结束,析构函数被调用return 0;
}

代码结果:

5. 关于编译器自动生成的析构函数,是否会完成一些事情呢?下面的程序我们会看到,编译器生成的默认析构函数,对自定义类型成员调用它的析构函数。

#include <iostream>using namespace std;// 自定义类,包含一个构造函数和析构函数
class CustomClass 
{
public:CustomClass() {cout << "CustomClass 的构造函数被调用。" << endl;}~CustomClass() {cout << "CustomClass 的析构函数被调用。" << endl;}
};// 另一个类,包含CustomClass类型的成员变量
class AnotherClass 
{
private:CustomClass myCustomObject; // 自定义类型成员变量public:// 缺少显式定义的构造函数和析构函数,// 编译器会自动生成默认的构造函数和析构函数
};int main() 
{AnotherClass obj; // 创建AnotherClass类型的对象obj// 当obj的作用域结束时(这里是大括号结束),默认析构函数会被自动调用// 这里obj对象生命周期结束,自动生成的析构函数会调用myCustomObject的析构函数return 0;
}

代码结果:

编译器自动生成的析构函数机制:
        1、编译器自动生成的析构函数对内置类型不做处理。
        2、对于自定义类型,编译器会再去调用它们自己的默认析构函数。 

6. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类。

拷贝构造函数

        在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。

        那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?

  拷贝构造函数的概念

概念:只有单个形参,该形参是对本类类型对象的引用(一般常用从const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

#include <iostream>using namespace std;class Date
{
public:Date(int year = 0, int month = 1, int day = 1)// 构造函数{_year = year;_month = month;_day = day;}Date(const Date& d)// 拷贝构造函数{_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2021, 5, 31);Date d2(d1); // 用已存在的对象d1创建对象d2return 0;
}

  拷贝构造函数的特性

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

        拷贝构造函数的函数名也与类名相同。

2、拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,
因为会引发无穷递归调用。

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d) // 正确写法//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、若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按
字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

#include <iostream>using namespace std;class Date
{
public:Date(int year = 0, 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 d1(2021, 5, 30);Date d2(d1); // 用已存在的对象d1创建对象d2d1.Print();d2.Print();return 0;
}

代码结果:

#include <iostream>using namespace std;class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time(const Time& t){cout << "Time::Time(const Time&)" << endl;_hour = t._hour;_minute = t._minute;_second = t._second;}
private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year = 1;int _month = 1;int _day = 1;// 自定义类型Time _t;
};int main()
{Date d1;// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构造函数Date d2(d1);return 0;
}

代码结果:

编译器自动生成的拷贝构造函数机制:
 1、编译器自动生成的拷贝构造函数对内置类型会完成浅拷贝(值拷贝)。
 2、对于自定义类型,编译器会再去调用它们自己的默认拷贝构造函数。

4、编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,还需要自己显式实现吗?
当然像日期类这样的类是没必要的。那么下面的类呢?

#include <malloc.h>
#include <stdlib.h>typedef int DataType;class Stack
{
public:Stack(size_t capacity = 10){_array = (DataType*)malloc(capacity * sizeof(DataType));if (nullptr == _array){perror("malloc申请空间失败");return;}_size = 0;_capacity = capacity;}void Push(const DataType& data){// CheckCapacity();_array[_size] = data;_size++;}~Stack(){if (_array){free(_array);_array = nullptr;_capacity = 0;_size = 0;}}
private:DataType* _array;size_t _size;size_t _capacity;
};int main()
{Stack s1;s1.Push(1);s1.Push(2);s1.Push(3);s1.Push(4);Stack s2(s1);return 0;
}

代码结果:

这里会发现上面的程序会崩溃掉?这里就需要我们以后讲的深拷贝去解决。

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

5、拷贝构造函数典型调用场景:

  •         使用已存在对象创建新对象。
  •         函数参数类型为类类型对象。
  •         函数返回值类型为类类型对象。

#include <iostream>using namespace std;class Date
{
public:Date(int year, int minute, int day){cout << "Date(int,int,int):" << this << endl;}Date(const Date& d){cout << "Date(const Date& d):" << this << endl;}~Date(){cout << "~Date():" << this << endl;}
private:int _year;int _month;int _day;
};Date Test(Date d)
{Date temp(d);return temp;
}int main()
{Date d1(2022, 1, 13);Test(d1);return 0;
}

代码结果:

注意:为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。

赋值运算符重载

  运算符重载

        C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

d1 == d2;// 可读性高(书写简单)
IsSame(d1, d2);// 可读性差(书写麻烦)// 目的就是让自定义类型可以像内置类型一样可以直接使用运算符进行操作。 

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

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

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@。
  • 重载操作符必须有一个类类型参数。
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义。
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this。
  • .*  ::  sizeof  ?:  .  注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

以重载 == 运算符作为例子: 

        1、可以将该运算符重载函数作为类的一个成员函数,该函数的第一个形参默认为this指针。

class Date
{
public:Date(int year = 0, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}bool operator==(const Date& d) // 运算符重载函数{return _year == d._year&&_month == d._month&&_day == d._day;}
private:int _year;int _month;int _day;
};

        2、也可以将该运算符重载函数放在类外面,但此时外部无法访问类中的成员变量,这时我们可以将类中的成员变量设置为共有(public),这样外部就可以访问该类的成员变量了(也可以用友元函数解决该问题)。并且在类外没有this指针,所以此时函数的形参我们必须显示的设置两个。

class Date
{
public:Date(int year = 0, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void Print(){cout << _year << "年" << _month << "月" << _day << "日" << endl;}int _year;int _month;int _day;
};
bool operator==(const Date& d1, const Date& d2) // 运算符重载函数
{return d1._year == d2._year&&d1._month == d2._month&&d1._day == d2._day;
}

  赋值运算符重载

1、赋值运算符重载格式

  • 参数类型:const 类类型&,传递引用可以提高传参效率。
  • 返回值类型:类类型&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值。
  • 检测是否自己给自己赋值。
  • 返回*this :要符合连续赋值的含义。

以重载 = 运算符作为例子: 

class Date
{
public:Date(int year = 0, int month = 1, int day = 1)// 构造函数{_year = year;_month = month;_day = day;}Date& operator=(const Date& d)// 赋值运算符重载函数{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;}void Print()// 打印函数{cout << _year << "年" << _month << "月" << _day << "日" << endl;}
private:int _year;int _month;int _day;
};

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

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}int _year;int _month;int _day;
};
// 赋值运算符重载成全局函数,注意重载成全局函数时没有this指针了,需要给两个参数
Date& operator=(Date& left, const Date& right)
{if (&left != &right){left._year = right._year;left._month = right._month;left._day = right._day;}return left;
}
// 编译失败:
// error C2801: “operator =”必须是非静态成员

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

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

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

#include <iostream>using namespace std;class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time& operator=(const Time& t){if (this != &t){_hour = t._hour;_minute = t._minute;_second = t._second;}return *this;}
private:int _hour;int _minute;int _second;
};class Date
{
private:// 基本类型(内置类型)int _year = 1970;int _month = 1;int _day = 1;// 自定义类型Time _t;
};int main()
{Date d1;Date d2;d1 = d2;return 0;
}

注意:对于日期类,编译器自动生成的赋值运算符重载函数就可以满足我们的需求,我们可以不用自己写。但是这也不意味着所有的类都不用我们自己写赋值运算符重载函数,当遇到一些特殊的类,我们还是得自己动手写赋值运算符函数的。

 注意区别以下代码所调用的函数:

Date d1(2021, 6, 1);// 构造函数
Date d2(d1);// 拷贝构造函数
Date d3 = d1;// 拷贝构造函数

构造函数和赋值运算符重载函数的使用场景: 

        拷贝构造函数:用一个已经存在的对象去构造初始化另一个即将创建的对象。
        赋值运算符重载函数:在两个对象都已经存在的情况下,将一个对象赋值给另一个对象。

const成员

  const修饰类的成员函数

        将const修饰的类成员函数称之为const成员函数,const修饰类成员函数,实际修饰的是类成员函数隐含的this指针,表明在该成员函数中不能对this指针指向的对象进行修改。

#include <iostream>using namespace std;class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << "Print()" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}void Print() const{cout << "Print()const" << endl;cout << "year:" << _year << endl;cout << "month:" << _month << endl;cout << "day:" << _day << endl << endl;}
private:int _year; // 年int _month; // 月int _day; // 日
};int  main()
{Date d1(2022, 1, 13);d1.Print();const Date d2(2022, 1, 13);d2.Print();return 0;
}

代码结果:

思考下面几个问题(经典面试题):
1、const对象可以调用非const成员函数吗?
2、非const对象可以调用const成员函数吗?
3、const成员函数内可以调用其他的非const成员函数吗?
4、非cosnt成员函数内可以调用其他的cosnt成员函数吗?

答案是:不可以、可以、不可以、可以

解释如下:
1、非const成员函数,即成员函数的this指针没有被const所修饰,我们传入一个被const修饰的对象,用没有被const修饰的this指针进行接收,属于权限的放大,函数调用失败。
2、const成员函数,即成员函数的this指针被const所修饰,我们传入一个没有被const修饰的对象,用被const修饰的this指针进行接收,属于权限的缩小,函数调用成功。
3、在一个被const所修饰的成员函数中调用其他没有被const所修饰的成员函数,也就是将一个被const修饰的this指针的值赋值给一个没有被const修饰的this指针,属于权限的放大,函数调用失败。
4、在一个没有被const所修饰的成员函数中调用其他被const所修饰的成员函数,也就是将一个没有被const修饰的this指针的值赋值给一个被const修饰的this指针,属于权限的缩小,函数调用成功。

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

        取地址操作符重载和const取地址操作符重载,这两个默认成员函数一般不用自己重新定义,使用编译器自动生成的就行了:

class Date
{
public:Date* operator&() // 取地址操作符重载{return this;}const Date* operator&()const // const取地址操作符重载{return this;}
private:int _year;int _month;int _day;
};

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

相关文章:

C++类与对象基础探秘系列(二)

目录 类的6个默认成员函数 构造函数 构造函数的概念 构造函数的特性 析构函数 析构函数的概念 析构函数的特性 拷贝构造函数 拷贝构造函数的概念 拷贝构造函数的特性 赋值运算符重载 运算符重载 赋值运算符重载 const成员 const修饰类的成员函数 取地址及const取地址操作…...

MyBatis-Plus核心功能详解:条件构造器、自定义SQL与Service接口

在Java的Web开发中&#xff0c;MyBatis-Plus作为MyBatis的增强工具&#xff0c;提供了许多实用的功能&#xff0c;极大地简化了数据库操作的开发过程。下面&#xff0c;我们将详细探讨MyBatis-Plus的三大核心功能&#xff1a;条件构造器、自定义SQL以及Service接口。 一、条件…...

莆田市C++专项选拔第二轮题4

题4&#xff1a;变换阵型 【题目描述】 盛隆同学刚学完C的二维数组和函数部分&#xff0c;于是他自己写了2个函数对二维数组进行练习。两个函数如下&#xff1a; int n, a[1005][1005]; // 注意&#xff0c;这里的n和数组a是全局变量 void f1() {for (int i 1; i < n; i)…...

AtCoder Regular Contest 177

A - Excange 题意 用这些零钱能否不找零地买这些物品 思路 因为 500 5 100 10 50 50 10 500 1 5005\times 10010\times 5050\times 10500\times 1 5005100105050105001。 所以说&#xff0c;我们这道题可以采用贪心算法&#xff0c;优先取大的减去目前零钱最大的…...

【C++】 C++ 编写 鸡兔同笼程序

文章目录 “鸡兔同笼”问题是一个经典的数学问题&#xff0c;要求根据总头数和总腿数来计算鸡和兔的数量。假设鸡有 2 条腿&#xff0c;兔有 4 条腿。可以通过以下步骤求解这个问题&#xff1a; 1 .设鸡的数量为 x&#xff0c;兔的数量为 y。2.根据题意&#xff0c;我们有以下…...

[动画详解]LeetCode151.翻转字符串里的单词

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到动画详解LeetCode算法系列 用通俗易懂的动画让算法题不再神秘 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成…...

如何使用 ArcGIS Pro 制作地震动画

在做某些汇报的时候&#xff0c;除了图文&#xff0c;如果有动画肯定会成为加分项&#xff0c;这里为大家介绍一下如何使用 ArcGIS Pro 制作地震动画&#xff0c;希望能对你有所帮助。 添加时间 在图层属性内&#xff0c;选择时间选项卡&#xff0c;图层时间选择每个要素具有…...

Unity 初步了解

1.Unity 是啥 Unity是一个实时3D互动内容创作和运营平台。它可以帮助游戏开发、美术、建筑、汽车设计、影视等行业的创作者将创意变为现实。Unity平台提供了一套完善的软件解决方案&#xff0c;用于创作、运营和变现任何实时互动的2D和3D内容&#xff0c;支持的平台包括手机、…...

爬虫学习(4)每日一笑

代码 import requests import re import osif __name__ "__main__":if not os.path.exists("./haha"):os.makedirs(./haha)url https://mlol.qt.qq.com/go/mlol_news/varcache_article?docid6321992422382570537&gameid3&zoneplat&webview…...

生产环境节点扩容方案

datanode节点扩缩容(1人天) 注意:新增节点需要走商务,节点扩容需要申请新的license 制品包下载 #内网下载(环境检查脚本) wget --user=admin --password=Y!bC2hx0TN@21cal http://10.69.71.180:8082/artifactory/product/qiudongyang/precheck/os-check20221127.tar…...

Spring线程池配置

配置Spring线程池,特别是ThreadPoolTaskExecutor,通常涉及设置一些关键参数以控制线程池的行为和性能。以下是一些基本的配置步骤: 定义配置类 首先,需要创建一个配置类,使用@Configuration注解标记,并启用异步执行功能,使用@EnableAsync注解。 @Configuration @Enab…...

Unity学习笔记---物理引擎

RigidBody 刚体 1&#xff0c;Gravity Scale 重力参数&#xff0c;是一个乘量参数&#xff0c;调整为0则不受重力影响。 2&#xff0c;Sleeping Mode 睡眠模式&#xff0c;分为永不睡眠/开始时睡眠/开始时不睡眠3种。如需要一直碰撞检测可以选择永不睡眠。 BoxCollider 碰撞…...

Vue与Java使用AES加密与解密

CBC模式&#xff08;通过偏移值进行加密&#xff0c;更具安全性&#xff09; 一、VUE&#xff1a; 1、安装 npm install crypto-js 2、编写公用js&#xff08;在common文件夹下创建一个crypto.js&#xff09; 注意&#xff1a;key最少要有16个字符&#xff0c;iv最少6个字符…...

B/S版+java开发的医院绩效考核系统maven+Visual Studio Code 医院绩效考核管理系统 提升医疗服务质量的关键

B/S版java开发的医院绩效考核系统mavenVisual Studio Code 医院绩效考核管理系统 提升医疗服务质量的关键 医院绩效评价系统的建设&#xff0c;优化医院绩效管理体系&#xff0c;规范化工作目标的设计、沟通、评价与反馈&#xff0c;改进和提供医院管理人员的管理能力和成效&am…...

汇昌联信科技:拼多多电商的运营流程有哪些?

在当今互联网高速发展的时代&#xff0c;电商平台层出不穷&#xff0c;其中拼多多以其独特的团购模式和低价策略迅速崛起&#xff0c;成为众多消费者和商家的新宠。那么&#xff0c;拼多多电商的运营流程究竟包含哪些环节呢?接下来&#xff0c;我们将从商品上架、营销推广、订…...

AI大模型探索之路-训练篇20:大语言模型预训练-常见微调技术对比

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…...

现代 c++ 一:c++11 ~ c++23 新特性汇总

所谓现代 c&#xff0c;指的是从 c11 开始的 c&#xff0c;从 c11 开始&#xff0c;加入一些比较现代的语言特性和改进了的库实现&#xff0c;使得用 c 开发少了很多心智负担&#xff0c;程序也更加健壮&#xff0c;“看起来像一门新语言”。 从 c11 开始&#xff0c;每 3 年发…...

【c++】全面理解C++多态:虚函数表深度剖析与实践应用

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;通过本篇文章&#xff0c;来详细理解多态的内容 目录 1.多态的定义及实现1.1多态的构成条件1.2虚函数的重写1.3 C11 override 和 final1.4重载、覆盖(重写)、隐藏…...

分享四种免费获取SSL的方式

SSL证书目前需要部署安装的网站很多&#xff0c;主要还是基于国内目前对证书的需求度在不断的升高&#xff0c;网站多了、服务器多了之后。网络安全问题就成为了大家不得不面对的一个重要的问题了。SSL证书的作用有很多&#xff0c;这里就不一一详述了&#xff0c;本期作品主要…...

2024.5.14晚训题解

非线性结构没懂的同学多去看看课程回放。 A题Overall Winner 题解 很基础的题目&#xff0c;输入字符串&#xff0c;用计数器去统计一下就好了。 因为赢的次数一样的时候优先判断前面的那个人赢&#xff0c;所以说两个人赢的次数相同的时候我们不必 去记录胜者。 #include<…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启&#xff0c;数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后&#xff0c;存在与用户组权限相关的问题。具体表现为&#xff0c;Oracle 实例的运行用户&#xff08;oracle&#xff09;和集…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...

基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解

JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用&#xff0c;结合SQLite数据库实现联系人管理功能&#xff0c;并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能&#xff0c;同时可以最小化到系统…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...