C++知识点:类和对象(自用)

类和对象

  • 1. 类和对象的关系
  • 2. 对象指针
  • 3. 在堆上创建对象
  • 4. 成员访问限定符
  • 5. 名字编码(Name Mangling)
  • 6.构造函数
  • 7.构造函数的重载
  • 8.初始化列表
  • 8. 成员变量初始化的顺序(通过初始化列表)
  • 9. 初始化 const 成员变量
  • 10. 析构函数
  • 11. 析构函数的执行时机!!
  • 12. 对象数组及其初始化
  • 12. 成员对象和封闭类
  • 13. 成员对象的初始化和析构顺序
  • 14. this 指针
  • 15. static静态成员变量
  • 16. static静态成员函数和普通成员函数的区别
  • 17. const成员变量和const成员函数
  • 18. const在函数的位置区别。
  • 18. const对象(常对象)
  • 19. 友元函数和友元类(friend关键字)
  • 20. string类
  • 21. 附录总结


引用:
[1]C语言中文网


1. 类和对象的关系

类是一种复杂数据类型的声明,并不占用内存空间。对象是类实例化后的具体实例,是类这个数据类型的一个变量,占用内存空间

类的定义(声明)不占用内存空间,所以在定义类时不能对成员变量进行初始化,因为没有地方存储数据。只有在创建对象以后才会给成员变量分配内存,这个时候就可以赋值了。

类名的首字母一般大写

类定义的最后有一个分号";",它是类定义的一部分,表示类定义结束了,不能省略。

除了创建单个对象,还可以创建对象数组:

class Student {int age;char *name;
};Student liyi; //创建单个对象
Student class_51[100]; //创建对象数组
liyi.age = 18; //创建对象以后才会给成员变量分配内存
liyi.name = 'liyi';

2. 对象指针

可以创建对象指针指向实例化后的对象。具体方法如下:

Student liyi; //创建单个对象
Student *pstu = &liyi;

3. 在堆上创建对象

知识点前提:栈区是程序自动管理的,不需要人为的释放内存。堆区是程序员自己管理的,必须自行释放内存。即,new和delete必须成对出现。

Student liyi; //在栈区实例化对象
Student *pstu = new Student; //在堆区实例化对象

我们在栈区创建的对象是有名字,即liyi。我们可以通过liyi这个对象名直接访问到对应的数据。所以,一般没必要用对象指针指向它。但是new操作符所创建的对象在堆区,返回的是一个指针,没有名字(简单来说就是,new创建的对象是匿名的)。如果没有对应的对象指针进行接收,则该对象无法访问了。

对象指针后,可以通过箭头->来访问对象的成员变量和成员函数。

通过对象名字访问成员使用点号.,通过对象指针访问成员使用箭头->。

4. 成员访问限定符

public: 类内可以访问,类外可以访问。
private:类内可以访问,类外不可以通过对象访问。
protected:类内可以访问,类外不可以通过对象访问,但是在它的派生类内部可以访问。

如果既不写 private 也不写 public,就默认为 private。

5. 名字编码(Name Mangling)

前提知识:C++对于对象进行分配内存时,只分配成员变量的内存。
不同对象的成员函数代码相同,所以不同对象分别分配自己的成员变量,同时共享成员函数代码。截图来自C语言中文网。在这里插入图片描述

那么如何确定每个对象自己的成员函数代码呢。这就需要借助C++编译器的名字编码。C++在每次编译的时候,会根据所属类名,命名空间,参数列表等不同对成员函数名进行重新编码。

在这里插入图片描述

6.构造函数

  • 构造函数会在创建对象时自动调用,不需要用户显式调用(用户也不能调用)。如果用户没有创建,则编译器会自动创建构造函数。一旦用户自己定义了构造函数,编译器则不会自动生成。
  • 构造函数必须是public属性,其他属性虽然不会报错,但是创建的构造函数没有意义。
  • 构造函数没有返回值,所以函数声明前不能有任何数据类型,并且函数体中不能有 return 语句。
  • 构造函数在实际开发中往往用来做一些初始化工作

7.构造函数的重载

构造函数是必须调用的,在创建对象的时候,必定会执行一个构造函数。如果构造函数重载,则必须有一组参数列表和其中一个构造函数相匹配。

8.初始化列表

class Student{
private:char* m_name;int m_age;
public:// 初始化列表方法:Student(char* name, int age):m_name(name), m_age(age){}//等价于Student(char* name, int age){ m_name = name; m_age=age;}
}

使用构造函数初始化列表并没有效率上的优势,仅仅是书写方便。

8. 成员变量初始化的顺序(通过初始化列表)

成员变量的初始化顺序与初始化列表中列出的变量的顺序无关,它只与成员变量在类中声明的顺序有关。

class Student{
private:int m_age;int m_age2;
public:Student(int age):m_age2(age), m_age(m_age2){}//错误理解:Student(int age){ m_age2= age; m_age=m_age2;}//正确理解:Student(int age){ m_age= m_age2; m_age2=age;}
}

在这里插入图片描述顺序修改后:
在这里插入图片描述
所以,尽量按照成员变量的声明的顺序进行初始化。

9. 初始化 const 成员变量

初始化 const 成员变量的唯一方法就是使用初始化列表。

错误方法:
在这里插入图片描述

10. 析构函数

  • 析构函数会在销毁对象时自动调用,不需要用户显式调用(用户也不能调用)。如果用户没有创建,则编译器会自动创建构造函数。析构函数是唯一的,不能重载!!!
  • 析构函数必须是public属性,其他属性虽然不会报错,但是创建的析构函数没有意义。
  • 析构函数没有返回值,所以函数声明前不能有任何数据类型,并且函数体中不能有 return 语句。
  • 析构函数在实际开发中往往用来做一些销毁内存(new,malloc创建的堆区变量,关闭文件)

示例:
在这里插入图片描述

11. 析构函数的执行时机!!

  • 在函数外创建的对象,是全局对象,类似于全局变量。数据存储在全局数据区,当全局作用域结束后,程序自动销毁存储在全局数据区的对象,调用其析构函数。
  • 在函数中创建的对象,是局部对象,类似于局部变量。数据存储在栈区,当函数结束后,程序自动销毁存储在栈区的对象,调用其析构函数。
  • 通过new创建的对象,也是局部对象,但是其存储在堆区,由程序员自动管理如果没有delete操作,则程序结束也不会调用其析构函数。所以,new申请的对象内存,一定要delete进行删除。
  • 析构遵循,先构造的后析构原则。

举例如下:
在这里插入图片描述

12. 对象数组及其初始化

对象数组的初始化,如果只有一个参数,可以隐式调用。如果由多个参数则应该显式调用

举例:

class Student{
private:char* m_name;int m_age;
public:// 没有参数Student():m_name("Null"),m_age(0){cout<<" construct m_name is "<< m_name << ", m_age is "<<m_age<<endl;}// 只有一个参数Student(char* name):m_name(name),m_age(0){cout<<" construct m_name is "<< m_name << ", m_age is "<<m_age<<endl;}// 两个参数(可类比多个)Student(char* name, int age):m_name(name), m_age(age){cout<<" construct m_name is "<< m_name << ", m_age is "<<m_age<<endl;}~Student(){cout<<" destruct m_name is "<< m_name << ", m_age is "<<m_age<<endl;}
};int main(){// 如果不给参数,默认调用Student()Student stu[2] = {}; // 如果只有一个参数,则可以隐式的直接给参数,例如"only_one_params"。Student stu2[2] = {"only_one_params"};// 第一个是隐式调用,第二个是默认构造(也是隐式)// 如果只有两个参数(多个),则需要显示调用,例如Student("only_two_params", 2)。Student stu3[2] = {"only_one_params", Student("only_two_params", 2)}; // 第二个就是显示调用。return 0;
}

在这里插入图片描述
注意:
如果是对象指针数组,则必须显示调用,并且创建几个对象就是几个对象。少的那个没有初始化,其指针值是随机的。

举例:

    Student* stu4[3] = {new Student("only_one_params"),new Student("only_two_params", 2),};

同时也可以验证之前的观点,new创建的对象,如果没有delete则不会进行析构。

12. 成员对象和封闭类

  • 当类中的成员变量是对象时,被称为成员对象。
  • 包含成员对象的类叫封闭类。

13. 成员对象的初始化和析构顺序

当封闭类创建对象时,需要先创建成员对象。对于成员对象的初始化,需要借助封闭类的构造函数初始化列表方法

特殊情况,当封闭类的构造函数没有对成员对象进行初始化时,如果成员对象有无参数的构造函数。则会通过无参数的构造函数进行初始化,如果有参数,则会报错。因此,封闭类必须对成员对象进行初始化。

成员对象的构造和析构,遵循先构造后析构的原则。即,先对成员对象进行构造,再对封闭类对象进行构造。先对封闭类对象进行析构,再对成员对象进行析构。

举例:

class Age{
private:int m_age;
public://无参数的构造函数Age():m_age(0){cout<<" construct Age , m_age is "<<m_age<<endl;}Age(int age):m_age(age){cout<<" construct Age, m_age is "<<m_age<<endl;}~Age(){cout<<" destruct Age, m_age is "<<m_age<<endl;}
};class Name{
private:char* m_family_name;char* m_last_name;
public:Name(char* f_name, char* l_name):m_family_name(f_name), m_last_name(l_name){cout<<" construct is "<< m_family_name<<" " << m_last_name <<endl;}~Name(){cout<<" destruct is "<< m_family_name<<" " << m_last_name <<endl;}
};// 封闭类
class Student{
private:// 成员对象Name m_c_name;Age m_c_age;
public:// 初始化构建Age类和Name类的成员对象。Student(char* f_name, char* l_name, int age):m_c_name(f_name, l_name), m_c_age(age){cout<<" construct Student is Class"<<endl;};// 测试是否调用Age类中无参数构造函数的成员对象Student(char* f_name, char* l_name):m_c_name(f_name, l_name){cout<<" construct Student is Class"<<endl;};~Student(){cout<<" destruct Student is Class"<<endl;}
};int main(){Student stu("li", "si", 22);
//    Student stu2("zhang", "san"); return 0;
}

从结果看,可以发现先通过构造函数创建成员对象m_c_name和成员对象m_c_age(顺序是成员对象声明顺序和初始化列表顺序无关),然后再通过封闭类构造函数创建对象stu。析构时的顺序先是封闭类析构函数,再是成员类析构函数。遵循先构造后析构原则。
(成员类析构函数顺序也是先构造后析构)
在这里插入图片描述

 Student stu2("zhang", "san"); //会调用无参数的构造函数

在这里插入图片描述

14. this 指针

this指针是一个const 指针,指向当前对象,且作用域范围是在成员函数内部。调用方法为"->"

注意:

  • this 是 const 指针,它的值是不能被修改的。
  • this 只能在成员函数内部使用。
  • 只有当对象被创建后 this 才有意义,因此不能在 static 成员函数中使用。
  • this 实际上是成员函数的一个隐式形参

15. static静态成员变量

不同对象之间成员变量相互独立。但是有时想要多个对象共享一个成员变量,此时就可以通过静态成员变量来实现。静态成员变量是一种特殊的成员变量,它被关键字static修饰

静态成员变量在类内声明,属于类,不属于对象。

static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,而是在(类外)初始化时分配。反过来说,没有在类外初始化的 static 成员变量不能使用。


初始化:

  • static 成员变量必须在类声明的外部初始化
  • 静态成员变量在初始化时不能再加 static,但必须要有数据类型
  • static 成员变量不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问。

static 成员变量和普通的 static 变量类似,都在内存分区中的全局数据区分配内存,到程序结束时才释放。

初始化时可以赋初值,也可以不赋值。如果不赋值,那么会被默认初始化为 0。全局数据区的变量都有默认的初始值 0,而动态数据区(堆区、栈区)变量的默认值是不确定的,一般认为是垃圾值。[1]

静态成员变量既可以通过对象名访问,也可以通过类名访问

举例:

class Student{
private:char* m_name;int m_age;
public:static int m_num;
public:// 初始化构建Age类和Name类的成员对象。Student(char* name, int age):m_name(name), m_age(age){m_num ++;};~Student(){}void show();
};void Student::show(){cout << "class num is "<<m_num<<endl;
}// 在类外对静态成员变量进行初始化。该数据存储在全局数据区,程序结束自动销毁。
int Student::m_num = 0;int main(){// 通过对象调用。(new Student("zhangsan", 20))->show();(new Student("lisi", 18))->show();(new Student("wangwu", 22))->show();//直接通过类名直接调用。cout << "check class num by class name. the num is "<<Student::m_num<<endl;return 0;
}
/*
输出:
class num is 1
class num is 2
class num is 3
check class num by class name. the num is 3
*/

16. static静态成员函数和普通成员函数的区别

静态成员函数与普通成员函数的根本区别在于:普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量静态成员函数)。

类似于python中的@staticmethod修饰的成员函数,其中没有self变量。

17. const成员变量和const成员函数

const成员变量只能通过初始化列表进行初始化,这点在第9点说过。

const成员函数可以访问类中所有的成员变量,但是不能修改它们的值。目的是为了保护数据。

方法是在成员函数头的尾部加上const关键字。

举例:

class Student{
private:char* m_name;int m_age;
public:
// 声明时函数头后加const关键字int getAge() const;
public:Student(char* name, int age):m_name(name), m_age(age){};~Student(){}
};// 定义时,函数头后也加const关键字
int Student::getAge() const{return m_age;
}int main(){Student stu("zhaoliu", 25);int num = stu.getAge();cout << "check class num by class name. the num is "<<num<<endl;return 0;
}

const成员函数不能修改内部的成员变量。如下图:
在这里插入图片描述

18. const在函数的位置区别。

  • 函数开头的 const 用来修饰函数的返回值,表示返回值是 const 类型,也就是不能被修改,例如const char * getname()。
  • 函数头部的结尾加上 const 表示常成员函数,这种函数只能读取成员变量的值,而不能修改成员变量的值,例如char * getname() const。

18. const对象(常对象)

如果对象被const修饰,则被称为常对象。在常对象中,只能使用const成员变量和const成员函数。

19. 友元函数和友元类(friend关键字)

当外部函数想要访问一个类中的private修饰的成员变量和成员函数时,可以借助friend关键字进行修饰,如果修饰的函数,则是友元函数,如果修饰的是类,则是友元类(友元类中所有的成员函数都是友元函数。)

  • 友元函数可以类外的函数(全局函数),也可以是类内的成员函数
  • friend关键字一定在类内。其声明的函数或者类,称为友元函数和友元类,可以访问该类中的所有成员变量。
  • friend修饰的函数,一定要有对象,对象指针或者对象引用。类比于this指针,友元函数和友元类中的成员函数,都需要借助对象对该类的private成员进行访问。
  • 友元函数和友元类是单向的不是双向的,例如B是A的友元类,可以访问A中所有成员变量。但是A不是B的友元类。
  • 友元函数和友元类不可传递,例如B是A的友元类,A是C的友元类,但是B不是C的友元类。

全局函数:

class Student{
private:char* m_name;int m_age;
public:Student(char* name, int age):m_name(name), m_age(age){};~Student(){}// 第二步:声明为Student类的友元函数,我们要访问Student类,就把friend定义到Student类中。friend void show(Student * ptu);
};//类外的全局函数想要访问Student类中的私有成员变量。
//第一步:参数需要有对象、对象指针或者对象引用
void show(Student * ptu){cout<< "this student name is "<< ptu->m_name << "  , age is "<<ptu->m_age<<endl;
}int main(){Student stu("zhaoliu", 25);// 直接调用全局函数show(),并把对象传进去。show(&stu);return 0;
}
/*
输出:
this student name is zhaoliu  , age is 25
*/

类内的成员函数:

class Student; // 提前声明,不然void show(Student * ptu);中Student未定义。class Test{//类内的成员函数想要访问Student类中的私有成员变量。//第一步:参数需要有对象、对象指针或者对象引用
public:void show(Student * ptu);
};class Student{
private:char* m_name;int m_age;
public:Student(char* name, int age):m_name(name), m_age(age){};~Student(){}// 第二步:声明为Student类的友元函数,我们要访问Student类,就把friend定义到Student类中。friend void Test::show(Student * ptu);
};void Test::show(Student * ptu){cout<< "this student name is "<< ptu->m_name << "  , age is "<<ptu->m_age<<endl;
}int main(){Student stu("zhaoliu", 25);// 直接调用全局函数show(),并把对象传进去。Test test;test.show(&stu);return 0;
}
/*
输出:
this student name is zhaoliu  , age is 25
*/

友元类:

// 除了friend void Test::show(Student * ptu);改为 friend Test;
// 其他把和类内成员函数声明为友元函数一样
class Student{
private:char* m_name;int m_age;
public:Student(char* name, int age):m_name(name), m_age(age){};~Student(){}// 第二步:声明为Student类的友元类,我们要访问Student类,就把friend定义到Student类中。friend Test;
};void Test::show(Student * ptu){cout<< "this student name is "<< ptu->m_name << "  , age is "<<ptu->m_age<<endl;
}

除非有必要,一般不建议把整个类声明为友元类,而只将某些成员函数声明为友元函数,这样更安全一些。

20. string类

  • 相比C语言中的字符串,string类对象声明的字符串数据,末尾不包括’\0’。
  • string类可以直接用 “=”进行赋值。
  • string类中有length()函数,该函数直接返回字符串的长度,因为末尾没有’\0’,所以返回的也是真是字符串长度。
  • string 类可以使用+或+=运算符来直接拼接字符串,不需要使用C语言中的 strcat()、strcpy()、malloc() 等函数来拼接字符串了,也不用担心空间不够会溢出。
  • string类转化为c语言的字符串,可以通过 “.c_str()”来实现。

string类的增上改查:

  • 插入字符串:
int main(){string s1, s2;s1 = "1234567890";s2 = "aaa";s1.insert(2, s2);//第一个是字符串下表,第二个是插入的字符或字符串cout<< s1 <<endl;return 0;
}
/*
输出:12aaa34567890
*/
  • 删除字符串:
int main(){string s1;s1 = "1234567890";s1.erase(5);// 第二个参数如果不指定,则从第一个下标(包含)后到末尾全删除cout<< s1 <<endl;s1.erase(2, 1); // 第一个是字符串下标,第二个是要删除几个字符。cout<< s1 <<endl;return 0;
}
/*
输出:
12345
1245
*/
  • 提取子字符串
int main(){string s1, s2;s1 = "1234567890";s2= s1.substr(5, 2);// 第一个是字符串下标,第二个是从下标开始(包含)提取多少个字符cout<< s2 <<endl;return 0;
}
/*
输出:
67
*/
  • 字符串查找
int main(){string s1, s2;s1 = "1234567890";s2 = "567";int index= s1.find(s2, 2); // 第一个参数是需要查找的子字符串,第二个参数是从第几个字符开始查,如果不指定则从第0个字符开始查。cout<< index <<endl;return 0;
}
/*
输出:
4
*/

还有其他两个查找函数:
rfind()函数:在find函数中,第二个参数表示从该参数下标开始查,而rfind函数则是从0字符查到第二个参数的下标。如果查不到返回-1

int main(){string s1, s2;s1 = "1234567890";s2 = "567";int index= s1.find(s2, 2);cout<< index <<endl;int index2= s1.rfind(s2, 2);cout<< index2 <<endl;int index3= s1.rfind(s2, 6);cout<< index3 <<endl;return 0;
}
/*
输出:
4
-1
4
*/

find_first_of() 函数:find_first_of() 函数用于查找子字符串和字符串共同具有的字符在字符串中首次出现的位置。

int main(){string s1, s2;s1 = "123 234 345";s2 = "a32";int index= s1.find_first_of(s2);cout<< index <<endl;return 0;
}
/*
输出:
1
*/

s1和s2共有的字符有“3”和“2”,在这两个中,首次出现下标是1。

21. 附录总结

该总结引用自[1]C语言中文网,如果想学习更详细的内容,可以去该网址学习。

  • 类的成员有成员变量和成员函数两种。

  • 成员函数之间可以互相调用,成员函数内部可以访问成员变量。

  • 私有成员只能在类的成员函数内部访问。默认情况下,class 类的成员是私有的,struct 类的成员是公有的。

  • 可以用“对象名.成员名”、“引用名.成员名”、“对象指针->成员名”的方法访问对象的成员变量或调用成员函数。成员函数被调用时,可以用上述三种方法指定函数是作用在哪个对象上的。

  • 对象所占用的存储空间的大小等于各成员变量所占用的存储空间的大小之和(如果不考虑成员变量对齐问题的话)。

  • 定义类时,如果一个构造函数都不写,则编译器自动生成默认(无参)构造函数和复制构造函数。如果编写了构造函数,则编译器不自动生成默认构造函数。一个类不一定会有默认构造函数,但一定会有复制构造函数。

  • 任何生成对象的语句都要说明对象是用哪个构造函数初始化的。即便定义对象数组,也要对数组中的每个元素如何初始化进行说明。如果不说明,则编译器认为对象是用默认构造函数或参数全部可以省略的构造函数初始化。在这种情况下,如果类没有默认构造函数或参数全部可以省略的构造函数,则编译出错。

  • 对象在消亡时会调用析构函数。

  • 每个对象有各自的一份普通成员变量,但是静态成员变量只有一份,被所有对象所共享。静态成员函数不具体作用于某个对象。即便对象不存在,也可以访问类的静态成员。静态成员函数内部不能访问非静态成员变量,也不能调用非静态成员函数。

  • 常量对象上面不能执行非常量成员函数,只能执行常量成员函数。

  • 包含成员对象的类叫封闭类。任何能够生成封闭类对象的语句,都要说明对象中包含的成员对象是如何初始化的。如果不说明,则编译器认为成员对象是用默认构造函数或参数全部可以省略的构造函数初始化。

  • 在封闭类的构造函数的初始化列表中可以说明成员对象如何初始化。封闭类对象生成时,先执行成员对象的构造函数,再执行自身的构造函数;封闭类对象消亡时,先执行自身的析构函数,再执行成员对象的析构函数。

  • const 成员和引用成员必须在构造函数的初始化列表中初始化,此后值不可修改。

  • 友元分为友元函数和友元类。友元关系不能传递。

  • 成员函数中出现的 this 指针,就是指向成员函数所作用的对象的指针。因此,静态成员函数内部不能出现 this 指针。成员函数实际上的参数个数比表面上看到的多一个,多出来的参数就是 this 指针。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL窗口函数详解

MySQL窗口函数详解 MySQL从8.0版本开始引入了窗口函数&#xff0c;这是一个强大的特性&#xff0c;可以大大简化复杂的数据分析任务。本文将详细介绍MySQL窗口函数的概念、语法和常见用法&#xff0c;并结合实际应用场景进行说明。 什么是窗口函数? 窗口函数是一种能够对结…

UE5+OpenCV配置(Windows11系统)

一、概述 因为需要在UE5中使用OpenCV这些工具进行配置&#xff0c;所以在网络上参考借鉴一些资料进行配置。查询到不少的资料&#xff0c;最后将其配置成功。在这里顺便记录一下自己的配置成功的过程。 二、具体过程 &#xff08;一&#xff09;版本 使用Windows11系统、UE5.…

CSS(九)——CSS 轮廓(outline)

CSS 轮廓&#xff08;outline&#xff09; 轮廓&#xff08;outline&#xff09;是绘制于元素周围的一条线&#xff0c;位于边框边缘的外围&#xff0c;可起到突出元素的作用。 轮廓&#xff08;outline&#xff09;属性指定元素轮廓的样式、颜色和宽度。 让我们用一个图来看…

基于Java中的SSM框架实现高校心理评测与分析系统项目【项目源码+论文说明】

基于Java中的SSM框架实现高校心理评测与分析系统演示 摘要 为了让学校和教师方面更好的深入了解学生的心理&#xff0c;有助于加强学生心理建设。该系统使用Java语言开发&#xff0c;系统架构采用SSM技术来实现功能性开发&#xff0c;MySQL数据库存放数据&#xff0c;实现了进…

springAOP理解及事务

AOP&#xff1a; springAOP是什么&#xff1a; AOP&#xff1a;Aspect Oriented Programming&#xff08;面向切面编程、面向方面编程&#xff09;&#xff0c;其实就是面向特定方法编程。 使用场景&#xff1a; 比如你想统计业务中每个方法的执行耗时&#xff0c;那我们最…

git cherry-pick用法

git cherry-pick 如何将我另一个分支上的某个提交合并到新的分支上 首先切换到新分支上git cherry-pick <commit_hash>例如&#xff1a;git cherry-pick f8a70c9

python实现接缝雕刻算法

python实现接缝雕刻算法 接缝雕刻算法步骤详解Python实现详细解释优缺点应用领域接缝雕刻算法(Seam Carving Algorithm)是一种内容感知的图像缩放技术,可以智能地改变图像的尺寸,而不会明显影响其重要内容。它通过动态规划的方式寻找图像中的“接缝”,即在图像中从上到下或…

jenkins自动化持续集成

一、持续集成优势 1.1 解放重复劳动 一次设置&#xff0c;多次复用。持续集成任务可以解放集成、测试、部署等重复性劳动&#xff0c;通过自动化任务能够显著提升集成频率。 1.2 更快解决问题 接入持续集成任务后&#xff0c;能够更早地感知变更后效果&#xff0c;及时进入…

pytest结合allure-pytest插件生成测试报告

目录 一、安装allure-pytest插件 二、下载allure 三、生成allure报告 四、效果展示 一、安装allure-pytest插件 二、下载allure 下载之后解压&#xff0c;解压之后还要配置环境变量&#xff08;把allure目录下bin目录配置到系统变量的path路径&#xff09;&#xff0c;下…

mysql语法介绍

MySQL 语法主要基于 SQL&#xff08;Structured Query Language&#xff09;标准&#xff0c;用于管理和操作关系型数据库。以下是一些基本的 MySQL 语句&#xff1a; 1.创建数据库&#xff1a; CREATE DATABASE database_name; 1.选择数据库&#xff1a; USE database_name;…

WPF使用TouchSocket实现Tcp client

文章目录 前言1、页面展示2、主页面UI代码2、TCP client的UI代码3、Tcp client后台代码实现4、UI与后台代码的关联 前言 在该篇的Demo中&#xff0c;您可以找到以下内容&#xff1a; 1、TouchSocket的使用&#xff1b; 2、CommunityToolkit.Mvvm的使用&#xff1b; 3、AvalonD…

GPT-4o Mini:探索最具成本效益的小模型在软件开发中的应用

随着人工智能技术的迅猛发展&#xff0c;自然语言处理&#xff08;NLP&#xff09;领域也取得了显著的进步。OpenAI 最新发布的 GPT-4o Mini 模型&#xff0c;以其卓越的性能和极具竞争力的价格&#xff0c;成为了广大开发者关注的焦点。作为一名长期关注人工智能及其在软件开发…

破局产品同质化:解锁3D交互式营销新纪元!

近年来&#xff0c;随着数字体验经济的蓬勃发展&#xff0c;3D交互式营销作为一种创新手段迅速崛起&#xff0c;它巧妙地解决了传统产品展示中普遍存在的缺乏差异性和互动性的问题&#xff0c;使您的产品在激烈的市场竞争中独树一帜&#xff0c;脱颖而出。 若您正面临产品营销…

【Python数据结构与算法】枚举----特殊密码锁

题目&#xff1a;特殊密码锁 描述 有一种特殊的二进制密码锁&#xff0c;由n个相连的按钮组成&#xff08;1<n<30&#xff09;&#xff0c;按钮有凹/凸两种状态&#xff0c;用手按按钮会改变其状态。 然而让人头疼的是&#xff0c;当你按一个按钮时&#xff0c;跟它相邻…

自定义协议(应用层协议)——网络版计算机基于TCP传输协议

应用层&#xff1a;自定义网络协议&#xff1a;序列化和反序列化&#xff0c;如果是TCP传输的&#xff1a;还要关心区分报文边界&#xff08;在序列化设计的时候设计好&#xff09;——粘包问题 1、首先想要使用TCP协议传输的网络&#xff0c;服务器和客户端都应该要创建自己…

无损放大图片工具

一、简介 1、Upscayl 是一款无损放大图片工具&#xff0c;支持CPU和GPU&#xff0c;扩图速度特别的快&#xff0c;而且效果特别的好。而且它有多种模型&#xff0c;比如说艺术动漫风格、真实风格、快速生成等等。最大支持16倍放大和亿级别像素&#xff0c;同时支持Windows、Mac…

Ruoyi-WMS本地运行

所需软件 1、JDK&#xff1a;8 安装包&#xff1a;https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.htmlopen in new window 安装文档&#xff1a;https://cloud.tencent.com/developer/article/1698454open in new window 2、Redis 3.0 安装包&a…

Weakly Supervised Contrastive Learning 论文阅读

Abstract 无监督视觉表示学习因对比学习的最新成就而受到计算机视觉领域的广泛关注。现有的大多数对比学习框架采用实例区分作为预设任务&#xff0c;将每个实例视为一个不同的类。然而&#xff0c;这种方法不可避免地会导致类别冲突问题&#xff0c;从而损害所学习表示的质量…

鸿蒙应用框架开发【多HAP】程序框架

多HAP 介绍 本示例展示多HAP开发&#xff0c;简单介绍了多HAP的使用场景&#xff0c;应用包含了一个entry HAP和两个feature HAP&#xff0c;两个feature HAP分别提供了音频和视频播放组件&#xff0c;entry中使用了音频和视频播放组件。 三个模块需要安装三个hap包&#xff…

玩游戏总缺少dll文件怎么办,免费修复DirectX方法

玩游戏或者运行程序时&#xff0c;突然蹦出个提示说“缺少xxxx.dll”&#xff0c;简直让人火大&#xff01;你是不是也遇到过这种情况&#xff0c;重新安装游戏也没用&#xff0c;各种错误提示让人崩溃&#xff1f;别急&#xff0c;阿星今天就来给你支个招&#xff0c;让这烦人…