C++类与对象(二)

一、默认成员函数

class A{};

像上面一样,一个什么都没有的类叫做空类,但是这个什么都没有并不是真正的什么都没有,只是我们看不见,空类里面其实是有6个默认成员函数的,当我们在类里面什么都不写的时候,编译器就会默认的帮我们编写6个默认成员函数。

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

二、构造函数

在上面的默认成员函数中我们就提到了构造函数主要完成初始化工作,我们再来看一下下面Date类的实现:

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Init(2022, 7, 5);d1.Print();Date d2;d2.Init(2022, 7, 6);d2.Print();return 0;
}

在这串类的实现中我们每次想要将其初始化都需要手动调用Init函数来输入数据,但是如果创建的数据很多的话也是很麻烦,那么我们就可以想想如何在创建对象的时候就将数据设计进去,此时我们就可以使用构造函数。

构造函数是一个特殊的成员函数,函数名字与类名相同,创建类类型对象的时候由编译器自动调用,保证每个数据成员都有一个合适的初始值,并且在对象的整个生命周期中只调用一次。

特性:

构造函数是特殊的成员函数,其名字叫做构造但是主要任务并不是开空间创建对象,而是初始化对象,其特征如下:

1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。
4. 构造函数可以重载。

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

6.无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为
是默认构造函数。就好比下面的一串代码:

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

我们在运行这串代码的时候编译器就会报错说:“Date::Date”: 对重载函数的调用不明确,此时就是因为写的第二个构造函数中的参数带来默认值,我们要是不带默认值就可以解决该问题。

三、析构函数

在上面的图中我们可以看到析构函数主要完成清理工作,他的功能是与构造函数相反的,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作.

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

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(),但是我们创建的是Date类型,那为什么编译器调用了Time类型呢,这是因为Date类里面有3个内置类型成员,销毁的时候不需要资源清理,系统在最后直接将其内存回收即可,而_t是我们的自定义类型成员,在d销毁的时候我们需要调用Time类型的析构函数进行该类的销毁,但是main函数并不能直接调用Time类型的析构函数,只能偶调用d的析构函数,但是此时我们并没有显式的编写d的析构函数编译器依旧能够调用Time的析构,这就是因为编译器给Date默认生成了一个可以调用Time类的析构函数,保证了所有的村部自定义对象都可以被正确的销毁.

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

四、拷贝构造函数

在日常生活中我们会看到“一模一样”的两个人,我们称其为双胞胎,而在创建对象的时候我们也会创建一个与已存在对象一模一样的新对象,这个时候我们就可以通过拷贝构造函数来进行实现了。

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

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

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;
}

我们如果按照上面的一串代码来写的话编译器就会因为无限递归而报错,这是因为我们使用了传值操作,如果这样写他就会一直调用Date(const Date d)函数导致无限的递归而怎么都传递不进去,这个时候我们就应该传引用,也就是对象的别名来防止递归。

3.若未显示定义,编译器会生成默认拷贝构造函数。默认的拷贝构造函数对象按照内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝或者值拷贝。

class Time
{
public:Time(){_hour = 1;_minute = 1;_second = 1;}Time(const Time& t){_hour = t._hour;_minute = t._minute;_second = t._second;cout << "Time::Time(const 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 d1;// 用已经存在的d1拷贝构造d2,此处会调用Date类的拷贝构造函数// 但Date类并没有显式定义拷贝构造函数,则编译器会给Date类生成一个默认的拷贝构//造函数Date d2(d1);return 0;
}

如果我们运行上面的一串代码我们就可以看到编译器输出了Time::Time(const Time&),这是因为在编译器生成的默认拷贝构造函数中,对于内置类型是按照字节方式直接拷贝的,而自定义类型则是调用其拷贝构造函数完成拷贝的。

4.编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,但是对于像下面的一些类我们还是需要自己显式实现的。

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;
}

这串代码运行之后就会造成程序的崩溃,这是因为什么呢?我们可以看到s1的构造函数是默认申请了10个空间的,我们并没有显式的实现Stack类的拷贝构造函数,于是编译器自己生成了默认的拷贝构造函数,这个拷贝构造函数是浅拷贝,也就是按字节序一个个的值拷贝,所以s1中的内容会原封不动的拷贝到s2中,就会导致s1与s2指向了同一片空间,而当程序退出的时候s1与s2是要销毁的,程序先将s2进行了销毁,此时该空间已经被释放,但是后来又销毁一次s1导致这片空间又被释放一次,从而导致了一片空间被释放两次从而程序崩溃。

所以当类中没有涉及资源申请的时候,拷贝构造函数写不写都可以,一旦涉及到了资源的申请的时候就一定要写出自己的拷贝构造函数防止一片空间被多次释放而程序崩溃。

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

·使用已存在对象创建新对象

·函数参数类型为类类型对象

·函数返回值类型为类类型对象

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

五、赋值运算符重载

1.运算符重载

我们在C++类中有很多的类类型,我们有时候想用简单的方法将数据进行改变,比如说我们想创建一个日期类,想计算日期的差或者加上一个数字计算之后的日期,我们如果直接使用编译器自带的+-符号并不能满足要求,于是C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

函数名字为:返回值operator后面接需要重载在的运算符符号

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

注意:

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

// 全局的operator==
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;
};
// 这里会发现运算符重载成全局的就需要成员变量是公有的,那么问题来了,封装性如何保证?
// 这里其实可以用我们后面学习的友元解决,或者干脆重载成成员函数。
bool operator==(const Date& d1, const Date& d2)
{return d1._year == d2._year&& d1._month == d2._month&& d1._day == d2._day;
}
void Test()
{Date d1(2018, 9, 26);Date d2(2018, 9, 27);cout << (d1 == d2) << endl;
}
class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// bool operator==(Date* this, const Date& d2)// 这里需要注意的是,左操作数是this,指向调用函数的对象bool operator==(const Date & d2){return _year == d2._year&& _month == d2._month&& _day == d2._day;}
private:int _year;int _month;int _day;
};
class Date
{
public:Date(int year = 1900, 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;}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;
};

我们仔细的看看上面的代码就可以知道使用operator重载的时候我们就可以看到函数其实是有自带一个做操作数的,便于编译。

2.赋值运算符重载

1. 赋值运算符重载格式
·参数类型:const T&,传递引用可以提高传参效率
·返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
·检测是否自己给自己赋值
·返回*this :要复合连续赋值的含义

class Date
{
public:Date(int year = 1900, 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;}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;
};

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.用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝,注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符重载完成赋值。

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;
}

赋值运算符的相关操作与拷贝构造函数类似,编译器生成的默认赋值运算符重载函数已经可以完成字节序的值拷贝了,但是如果涉及资源空间的管理就一定需要自己来显式实现。

3.前置++和后置++重载

我们在重载的过程中可能会发现一个问题,前置++与后置++操作符长得一模一样,那该如何进行重载和区分呢?我们可以知道的是听他们的返回值肯定是有区别的,一个是++之前的结果,那就返回本身,一个是++之后的结果,那就新建一个变量进行返回。再就是在()内部加上int进行区分。

class Date
{
public:Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// 前置++:返回+1之后的结果// 注意:this指向的对象函数结束后不会销毁,故以引用方式返回提高效率Date& operator++(){_day += 1;return *this;}// 后置++:// 前置++和后置++都是一元运算符,为了让前置++与后置++形成能正确重载// C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器//自动传递// 注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存//一份,然后给this + 1//而temp是临时对象,因此只能以值的方式返回,不能返回引用Date operator++(int){Date temp(*this);_day += 1;return temp;}
private:int _year;int _month;int _day;
};

六、日期类的实现

我们已经学习了运算符的重载,我们便可以尝试一下使用日期进行加减或者计算。我们来看代码实现:

//date.hpragma once
#include<iostream>
using namespace std;
#include<assert.h>
class Date
{// Ԫfriend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);
public:bool CheckDate() const;Date(int year = 1900, int month = 1, int day = 1);void Print() const;// Ĭinlineint GetMonthDay(int year, int month) const{assert(month > 0 && month < 13);static int monthDayArray[13] = { -1, 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))){return 29;}return monthDayArray[month];}bool operator<(const Date& d) const;bool operator<=(const Date& d) const;bool operator>(const Date& d) const;bool operator>=(const Date& d) const;bool operator==(const Date& d) const;bool operator!=(const Date& d) const;Date operator+(int day) const;Date& operator+=(int day);Date operator-(int day) const;Date& operator-=(int day);// d1++;// d1.operator++(0);Date operator++(int);// ++d1;// d1.operator++();Date& operator++();// d1--;// d1.operator--(0);Date operator--(int);// --d1;// d1.operator--();Date& operator--();// d1 - d2int operator-(const Date& d) const;//void operator<<(ostream& out);Date* operator&(){//return this;//return nullptr;return (Date*)0x2673FF40;}const Date* operator&() const{//return this;//return nullptr;return (Date*)0x2673FE30;}
private:int _year;int _month;int _day;
};ostream& operator<<(ostream& out, const Date& d);
istream& operator>>(istream& in, Date& d);//date.cpp#include"date.h"void Date::Print() const
{cout << _year << "-" << _month << "-" << _day << endl;
}
bool Date::CheckDate() const
{if (_month > 12||_month<1||_day<1||_day>GetMonthDay(_year,_month)){return false;}else{return true;}
}
Date::Date(int year, int month, int day)
{_year = year;_month = month;_day = day;if (!CheckDate()){cout << "非法日期:";Print();}
}
bool Date::operator<(const Date& d) const
{if (_year < d._year){return true;}else if (_year == d._year){if (_month < d._month){return true;}else if (_month == d._month){if (_day < d._day){return true;}else{return false;}}else{return false;}}else{return false;}
}
bool Date::operator==(const Date& d) const
{return _year == d._year && _month == d._month && _day == d._day;
}
bool Date::operator<=(const Date& d) const
{return *this == d || *this < d;
}
bool Date::operator>(const Date& d) const
{/*if (_year > d._year){return true;}else if (_year == d._year){if (_month > d._month){return true;}else if (_month == d._month){return _day > d._day;}}return false;*/return !(*this <= d);
}
bool Date::operator>=(const Date& d) const
{return !(*this < d);
}
bool Date::operator!=(const Date& d) const
{return !(*this == d);
}
Date& Date::operator+=(int day) 
{if (day < 0){return *this -= (-day);}_day += day;while (_day > GetMonthDay(_year, _month)){_day -= GetMonthDay(_year, _month);_month++;if (_month > 12){_year++;_month = 1;}}return *this;
}
Date Date::operator+(int day) const
{Date tmp = *this;tmp += day;return tmp;
}
Date& Date::operator-=(int day)
{if (day < 0){return *this += (- day);}_day -= day;while (_day <= 0){_day += GetMonthDay(_year, _month);_month--;if (_month == 0){_year--;_month = 12;}}return *this;
}
Date Date::operator-(int day) const
{Date tmp = *this;tmp -= day;return tmp;
}
Date Date::operator++(int)
{Date tmp = *this;*this += 1;return tmp;
}
Date& Date::operator++()
{*this += 1;return *this;
}
Date Date::operator--(int)
{Date tmp = *this;*this -= 1;return tmp;
}
Date& Date::operator--()
{*this -= 1;return *this;
}
int Date::operator-(const Date& d) const
{int flag = -1;Date min = *this;Date max = d;if (*this > d){min = d;max = *this;flag = 1;}int n = 0;while (min != max){max--;n++;}return n * flag;
}
ostream& operator<<(ostream& out, const Date& d)
{out << d._year << "年" << d._month << "月" << d._day << "日" << endl;return out;
}
istream& operator>>(istream& in, Date& d)
{while (1){cout << "请依次输入年月日>>";in >> d._year >> d._month >> d._day;if (!d.CheckDate()){cout << "输入日期非法:";d.Print();cout << "请重新输入日期:" << endl;}else{break;}}return in;
}//test.cpp#include"date.h"int main()
{Date const a1(2023, 6, 10);Date const a2(2024, 7, 20);int const ret = a2 - a1;cout << ret << endl;Date const a3 = a1 + 100;a3.Print();return 0;
}

七、const成员

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

class Date
{
public:void Display(const Date *this){cout << this->_year << "-" << this->_month;cout << "-" << this->_day << endl;}
private:int _year;int _month;int _day;
};
class Date
{
public:void Display() const{cout << _year << "-" << _month;cout << "-" << _day << endl;}
private:int _year;int _month;int _day;
};

所以我们在前面写的一些函数为了防止不小心将类的成员修改就可以再函数之后加上const进行保护。

感谢各位的支持~~~

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

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

相关文章

数据结构与算法-03链表-03

递归与迭代 由一个问题引出 假设我们要计算 一个正整数的阶乘, N! 。 从数学上看 1&#xff01; 1 2&#xff01; 2 x 1 3! 3 x 2 x 1 4! 4 x 3 x 2 x 1 5! 5 x 4 x 3 x 2 x 1 : n! n x (n-1) x (n-2) x (n-3) x ... 1我们推出一般公式 f(1) 1 f(n) n * f(n-1…

spring6:2入门

spring6&#xff1a;2入门 目录 spring6&#xff1a;2入门2.1、环境要求2.2、构建模块2.3、程序开发2.3.1、引入依赖2.3.2、创建java类2.3.3、创建配置文件2.3.4、创建测试类测试2.3.5、运行测试程序 2.4、程序分析2.5、启用Log4j2日志框架2.5.1、Log4j2日志概述2.5.2、引入Log…

汽车IVI中控开发入门及进阶(三十五):架构QML App Architecture Best Practices

在Qt/QML工程的架构中,架构很重要,虽然本身它有分层,比如QML调用资源文件(图片等)显示GUI界面,后面的CPP文件实现界面逻辑,但是这个分类还有点粗。在实际开发中,界面逻辑也就是基于类cpp的实现,也开始使用各种面向对象的设计模式,实现更加优秀的开发架构,这点尤其在…

import是如何“占领满屏“

import是如何“占领满屏“的&#xff1f; 《拒绝使用模块重导&#xff08;Re-export&#xff09;》 模块重导是一种通用的技术。在腾讯、字节、阿里等各大厂的组件库中都有大量使用。 如&#xff1a;字节的arco-design组件库中的组件&#xff1a;github.com/arco-design… …

(软件测试文档大全)测试计划,测试报告,测试方案,压力测试报告,性能测试,等保测评,安全扫描测试,日常运维检查测试,功能测试等全下载

1. 引言 1.1. 编写目的 1.2. 项目背景 1.3. 读者对象 1.4. 参考资料 1.5. 术语与缩略语 2. 测试策略 2.1. 测试完成标准 2.2. 测试类型 2.2.1. 功能测试 2.2.2. 性能测试 2.2.3. 安全性与访问控制测试 2.3. 测试工具 3. 测试技术 4. 测试资源 4.1. 人员安排 4.2. 测试环境 4.2.…

抽象工厂模式的理解和实践

在软件开发中&#xff0c;设计模式是解决常见问题的最佳实践。抽象工厂模式是一种创建型设计模式&#xff0c;提供了一种创建一系列相关或相互依赖对象的接口&#xff0c;而无需指定它们的具体类。本文将详细解释抽象工厂模式的概念、结构、优点、缺点&#xff0c;并通过Java代…

算法日记(2024.12.05)

1.对称二叉树 给你一个二叉树的根节点 root &#xff0c; 检查它是否轴对称。 示例 1&#xff1a; 输入&#xff1a;root [1,2,2,3,4,4,3] 输出&#xff1a;true 示例 2&#xff1a; 输入&#xff1a;root [1,2,2,null,3,null,3] 输出&#xff1a;false 提示&#xff1…

【知识点】图与图论入门

何为图论 见名知意&#xff0c;图论 (Graph Theory) 就是研究 图 (Graph) 的数学理论和方法。图是一种抽象的数据结构&#xff0c;由 节点 (Node) 和 连接这些节点的 边 (Edge) 组成。图论在计算机科学、网络分析、物流、社会网络分析等领域有广泛的应用。 如下&#xff0c;这…

【书生大模型实战营】Linux 基础知识-L0G1000

前言&#xff1a;书生大模型实战营是上海人工智能实验室开展的大模型系列实践活动&#xff0c;提供免费算力平台&#xff0c;学员通过闯关式任务&#xff0c;可获得免费算力和存储&#xff0c;助力项目实践。本期是第4期&#xff0c;时间从十一月份开始&#xff0c;持续到十二月…

【软件安全】软件安全设计规范,软件系统安全设计制度(Word原件)

1.1安全建设原则 1.2 安全管理体系 1.3 安全管理规范 1.4 数据安全保障措施 1.4.1 数据库安全保障 1.4.2 操作系统安全保障 1.4.3 病毒防治 1.5安全保障措施 1.5.1实名认证保障 1.5.2 接口安全保障 1.5.3 加密传输保障 1.5.4终端安全保障 软件全面文档清单涵盖以下核心内容&a…

你是如何找bug的?bug分析的正确打开方式

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 Bug严重级别(Severity&#xff0c;Bug级别)&#xff1a;是指因缺陷引起的故障对软件产品的影响程度&#xff0c;由测试人员指定。 A-Crash&#xff1a;造成系统或…

WGCNA分析流程及内容解读

文章标题&#xff1a;通过 WGCNA 和机器学习识别和验证与免疫和氧化应激相关的糖尿病肾病诊 发表年限&#xff1a;2023年 期刊&#xff1a;Frontiers in Immunology 影响因子&#xff1a;5.7 研究背景&#xff1a; 糖尿病肾病&#xff08;DN&#xff09;以蛋白尿、高血压和…

【MySQL 进阶之路】锁详解

MySQL 锁详解 1. 锁的基本概念 锁在数据库中是用来保证数据一致性和防止并发冲突的一种机制。MySQL 中的锁可以分为不同的类型和粒度&#xff0c;每种锁都有特定的使用场景和特点。了解锁的类型、作用以及如何避免锁带来的问题是提升数据库性能和避免数据冲突的关键。 2. 锁…

qsort函数用法,以及模拟实现

函数定义 基于快速排列的一个函数&#xff0c;它的四个参数的含义&#xff1a; 1、void* base&#xff0c;是排序开始的地址 2、size_t num 想要排列的个数 3、size_t size 排列对象&#xff0c;一个占多少空间&#xff08;字节&#xff09; 4、int (*comper)(void*,voi…

CentOS7虚拟机 网络适配器 NAT模式和桥接模式区别

一、环境介绍 宿主机&#xff1a;Windows电脑 虚拟机&#xff1a;VMware下的CentOS7 局域网&#xff1a;路由器下的各真实主机组成的网络 内部局域网&#xff1a;宿主机构建的一个内部网路 二、NAT和桥接网络链接模式区别 NAT模式&#xff1a;相当于宿主机构建一个内部局域网&a…

全面解析DApp开发中的智能合约设计

在DApp的开发过程中&#xff0c;智能合约的设计起到了至关重要的作用。智能合约是运行在区块链上的程序&#xff0c;负责处理和执行DApp中的逻辑、交易和数据存储。下面我们将深入探讨智能合约的设计原则、挑战和优化方法&#xff0c;帮助开发者掌握如何设计高效、安全的智能合…

锐捷Web认证

文章目录 Web认证二代 Web 认证配置 &#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;Datacom专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年12月6日11点40分 Web认证 Portal 认证、Web认证 Web认证的介绍 Web 认证使用浏览器进行身份验…

KernelShark在ubuntu24.04.01的编译

KernelShark在ubuntu24.04.01的编译 写在前面具体过程装ubuntu24.04.01安装depends下载代码如何编译cmake 输出make 输出 如何安装 初步启动Add the User to the perf Group 简单的使用trace-cmd抓包 来看我的文章&#xff0c;必有所得。 平凡中&#xff0c;总有我帮您踩过的坑…

解决Unity编辑器Inspector视图中文注释乱码

1.问题介绍 新创建一个脚本&#xff0c;用VS打开编辑&#xff0c;增加一行中文注释保存&#xff0c;在Unity中找到该脚本并选中&#xff0c;Inspector视图中预览的显示内容&#xff0c;该中文注释显示为乱码&#xff0c;如下图所示&#xff1a; 2.图示解决步骤 按上述步骤操作…

【AIGC半月报】AIGC大模型启元:2024.12(上)

【AIGC半月报】AIGC大模型启元&#xff1a;2024.12&#xff08;上&#xff09; &#xff08;1&#xff09;OpenAI-12日发布会&#xff08;持续更新中........&#xff09;Day01-12.06&#xff1a;o1满血版上线&#xff08;已发布&#xff09;Day02-12.07&#xff1a;强化微调&a…