[C++] 由浅入深理解面向对象思想的组成模块

news2024/11/15 8:20:34

Kevin的技术博客.png

文章目录

  • (一) 类的默认成员函数
  • (二) 构造函数
    • 构造函数的特征
    • 构造函数示例
      • 无参构造
      • 带参构造
    • 冲突:全缺省参数的构造函数与无参构造函数
  • (三)析构函数
    • 特性
    • 析构函数的析构过程解析
  • (四)拷贝构造函数
    • 什么是拷贝构造?
    • 特性
      • 为什么拷贝构造函数参数一定要以引用的形式?
      • 值拷贝/浅拷贝
      • 深拷贝
      • 返回值为引用
  • (五)运算符重载
    • 如何定义及使用
      • 定义格式及使用
    • 前置++/后置++
      • 前置++
      • 后置++
    • 重载“<<” “>>”
  • (六)取地址运算符重载
    • const成员函数
    • 取地址运算符重载

(一) 类的默认成员函数

默认成员函数就是⽤⼾没有显式实现,编译器会⾃动⽣成的成员函数称为默认成员函数。

六个默认成员函数:

  • 构造函数
  • 析构函数
  • 拷贝构造函数
  • 复制重载函数
  • 取地址重载函数(普通对象,const对象)

(二) 构造函数

在C++中,构造函数是专门用于初始化对象的方法。当创建类的新实例时,构造函数会自动被调用。通过构造函数,我们可以确保对象在创建时就被赋予合适的初始状态。下面将详细解释如何使用构造函数进行初始化操作,并以Date类为例进行说明。

// 创建一个Date类
class Date 
{  
public:  
    // 成员函数...  
private:  
    int _year;  
    int _month;  
    int _day;  
};

构造函数的特征

  1. 构造函数的特点:
  2. 函数名与类名相同。
  3. ⽆返回值。
  4. 对象实例化时系统会⾃动调⽤对应的构造函数。
  5. 构造函数可以重载。
  6. 如果类中没有显式定义构造函数,则C++编译器会⾃动⽣成⼀个⽆参的默认构造函数,⼀旦用户显式定义编译器将不再⽣成。
  7. ⽆参构造函数全缺省构造函数拷贝构造这三个我们不写构造时编译器默认⽣成的构造函数,都叫做默认构造函数。但是这三个函数有且只有⼀个存在,不能同时存在。⽆参构造函数和全缺省构造函数虽然构成函数重载,但是调⽤时会存在歧义。要注意很多同学会认为默认构造函数是编译器默认⽣成那个叫默认构造,实际上⽆参构造函数、全缺省构造函数也是默认构造,总结⼀下就是不传实参就可以调⽤的构造就叫默认构造。
  8. C++把类型分为内置类型和自定义类型,内置类型就是语言提供的原生数据类型,例:int/char/double/指针等;自定义类型指的是我们用class/struct自己定义的类型。编译器的默认生成的构造函数与之相关:
    • 内置类型:编译器默认生成的构造对内置类型没有初始化的要求。
    • 自定义类型:生成的构造函数会调用自定义类型的构造函数,所以在自定义类型的构造函数中需要对内置类型进行初始化。
  9. 请注意第8条特征

构造函数示例

无参构造

无参构造函数允许我们创建Date对象而不提供任何参数。但是,需要注意的是,如果我们不在无参构造函数中初始化成员变量,那么这些变量的初始值将是未定义的,这可能会导致程序出错。
Date d1; // 调用无参构造函数

class Date 
{  
public:  
    // 1. 无参构造函数  
    Date() 
    {  
        // 在这里可以添加一些初始化代码,例如设置默认日期  
        // 例如:_year = 2000; _month = 1; _day = 1;  
    }  
  
    // 其他成员函数...  
  
private:  
    int _year;  
    int _month;  
    int _day;  
};

带参构造

带参构造可以和无参构造函数重载,因为在之后调用的时候不会受影响,可以与之后讲解的全缺省构造函数和无参构造函数之间的不能函数重载的进行区别。

带参构造函数可以在对对象进行初始化的时候进行传参,传参的数值会直接进行初始化对象中的成员变量。
Date date2(2023, 3, 15); // 调用带参构造函数创建对象,并初始化日期为2023年3月15日

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

在这个带参构造函数中,我们通过参数year、month和day来初始化_year、_month和_day成员变量。这样,我们就可以在创建Date对象时直接指定日期了。

注意区别创造对象的格式:

Date d1; // 调用无参构造函数
Date d2(2015, 1, 1); // 调用带参的构造函数

冲突:全缺省参数的构造函数与无参构造函数

C++11 😗*内置类型成员变量在类中声明时可以给默认值。 **

全缺省参数的构造函数结构类似于以下代码:

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

特点:会在参数列表中进行类似于赋值的操作
这个构造函数接受三个参数,并且每个参数都有一个默认值。这意味着,在创建Date对象时,你可以选择性地提供这些参数。如果你没有为任何一个参数提供值,那么它们将使用默认值(即1900年1月1日)。

思考:以下代码是否可以编译通过?

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

结论:无法通过。
原因:

  • 语法可以存在、调用存在歧义。
  • 无参构造和全缺省存在歧义,当使用不传参创建对象Date d;的时候编译器无法抉择选择构造函数。
  • 推荐使用全缺省参数的构造函数。

(三)析构函数

对象在销毁时(生命周期结束时)会自动调用析构函数,完成对象中资源的清理工作(如释放动态分配的内存、关闭文件等

特性

  1. 析构函数名是在类名前面加上“ ~ ” :~Stack() { }
  2. 无参数和返回值;
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数;
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数,即使我们显式写析构函数,对于⾃定义类型成员也会调⽤他的析构,也就是说⾃定义类型成员⽆论什么情况都会⾃动调⽤析构函数。

注意:

  • 析构函数主要是为了清理申请的资源,防止内存泄漏;
  • 同一域内后定义的对象先析构。
typedef int DataType;
class Stack
{
public:
    Stack(size_t capacity = 3)
    {
        _array = (DataType*)malloc(sizeof(DataType) * capacity);
        if (nullptr == _array)
        {
            perror("malloc申请空间失败!!!");
            return;
        }
        _capacity = capacity;
        _size = 0;
    }
    void Push(DataType data)
    {
        if (_size == _capacity)
        {
            // 扩展数组大小
            _capacity *= 2;
            _array = (DataType*)realloc(_array, sizeof(DataType) * _capacity);
            if (nullptr == _array)
            {
                perror("realloc扩展空间失败!!!");
                return;
            }
        }
        _array[_size] = data;
        _size++;
    }
    // 其他方法...
    ~Stack()
    {
        if (_array)
        {
            free(_array);
            _array = nullptr;
            _capacity = 0;
            _size = 0;
        }
    }
private:
    DataType* _array;
    size_t _capacity;
    size_t _size;
};
void TestStack()
{
    Stack s;
    s.Push(1);
    s.Push(2);
}

int main() 
{
    TestStack();
    return 0;
}

析构函数的析构过程解析

当正确使用析构函数后就不用担心程序中有内存泄漏的情况了,因为在每次该对象生命周期结束后都会自动调用析构函数,流程如下:

  • ①准备出生命周期

image.png

  • ②出生命周期,进入析构函数

image.png

  • ③析构函数执行完毕,对象销毁

image.png

(四)拷贝构造函数

什么是拷贝构造?

如果⼀个构造函数的第⼀个参数是⾃⾝类类型的引⽤,且任何额外的参数都有默认值,则此构造函数
也叫做拷⻉构造函数,拷⻉构造是⼀个特殊的构造函数。

特性

  1. 拷贝构造函数是构造函数的一个重载形式
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
  3. C++规定⾃定义类型对象进⾏拷⻉⾏为必须调⽤拷⻉构造,所以这⾥⾃定义类型传值传参和传值返回都会调⽤拷⻉构造完成**(只要是拷贝行为就会调用拷贝构造)**。
  4. 若未显式定义拷⻉构造,编译器会⽣成⾃动⽣成拷⻉构造函数。⾃动⽣成的拷⻉构造对内置类型成员变量会完成值拷⻉/浅拷⻉(⼀个字节⼀个字节的拷⻉),对⾃定义类型成员变量会调⽤他的拷⻉构造(深拷贝)

为什么拷贝构造函数参数一定要以引用的形式?

// 错误的写法
Date(const Date d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
}

以日期类举例:若使用Date(const Date d)传参进行拷贝构造时,在传参的时候例如是以Date(d2)来传参那么就相当于用d = d2,这样的话由于是在构造一个新的对象d2,所以会继续调用拷贝构造函数,如此下去就会造成无限循环的去调用拷贝构造函数而不会执行结束。
image.png

Date(const Date& d)
{
    _year = d._year;
    _month = d._month;
    _day = d._day;
}

所以正确的写法应该如上代码所示。

在写的参数的时候用const是为了保证数据的安全性,防止被修改。

值拷贝/浅拷贝

浅拷贝是指在创建对象的副本时,只复制对象本身,而不复制对象所持有的资源(如动态分配的内存)。浅拷贝可能导致的问题是,如果原始对象和副本对象都尝试释放相同的资源,就可能发生内存泄漏或双重释放错误。

深拷贝

深拷贝是指在创建对象的副本时,不仅复制对象本身,还复制对象所持有的所有资源。这意味着如果对象包含指针指向动态分配的内存,深拷贝会为副本对象分配新的内存,并复制原始内存中的数据。

  • 对于每个指针成员,分配新的内存并复制数据。
  • 对于非指针成员,直接复制值。
  • 通过深拷贝即可解决浅拷贝中:释放相同的资源错误的问题。

在默认生成的拷贝构造函数和赋值运算符重载中使用的是浅拷贝还是深拷贝取决于自定义成员变量的拷贝构造函数,当没有空间申请的时候一般会使用浅拷贝,但是在有空间申请的时候会进行深拷贝,前提是自定义成员变量的拷贝构造函数有申请空间进行拷贝,这样上一级自动生成的默认构造函数才会进行正确调用。
例如:用两个栈实现队列

typedef int STDataType;
class Stack
{
	public :
	Stack(int n = 4)
	{
		_a = (STDataType*)malloc(sizeof(STDataType) * n);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败");
			return;
		} 
		_capacity = n;
		_top = 0;
	}

    // 拷贝构函数
	Stack(const Stack& st)
	{
		
			// 需要对_a指向资源创建同样⼤的资源再拷⻉值
			_a = (STDataType*)malloc(sizeof(STDataType) * st._capacity);
		if (nullptr == _a)
		{
			perror("malloc申请空间失败!!!");
			return;
		} 
			memcpy(_a, st._a, sizeof(STDataType) * st._top);
			_top = st._top;
			_capacity = st._capacity;
	}
	void Push(STDataType x)
	{
		if (_top == _capacity)
		{
			int newcapacity = _capacity * 2;
			STDataType* tmp = (STDataType*)realloc(_a, newcapacity *
				sizeof(STDataType));
			if (tmp == NULL)
			{
				perror("realloc fail");
				return;
			} 
				_a = tmp;
			_capacity = newcapacity;
		} 
			_a[_top++] = x;
	} 
		~Stack()
	{
		cout << "~Stack()" << endl;
		free(_a);
		_a = nullptr;
		_top = _capacity = 0;
	}
private:
	STDataType* _a;
	size_t _capacity;
	size_t _top;
};
// 两个Stack实现队列
class MyQueue
{
	
		public :
private:
	Stack pushst;
	Stack popst;
};

int main()
{
    MyQueue mq1;
    MyQueue mq2 = mq1;

    return 0;
}

MyQueue⾃动⽣成的拷⻉构造,会⾃动调⽤Stack拷⻉构造完成pushst/popst 的拷⻉,只要Stack拷⻉构造⾃⼰实现了深拷⻉,当用MyQueue自动生成的拷贝构造的时候就会进行深拷贝从而完成拷贝。

返回值为引用

返回值为引用要注意返回的值为局部对象还是全局对象:

  • 当返回的为局部对象的时候当出了局部域的时候局部对象的空间就会销毁,返回的引用就会成为野引用,;
  • 当返回的对象为全局引用或者申请了空间的对象则不会由野引用的问题,但是在返回的时候会调用拷贝构造。

如下代码,返回值为引用,即会出现也引用的问题:

Date& Func2()
{
    Date tmp(2024, 7, 5);
    tmp.Print();
    return tmp;
}

正确应该如下:

Date Func2()
{
    Date tmp(2024, 7, 5);
    tmp.Print();
    return tmp;
}

(五)运算符重载

当运算符被⽤于类类型的对象时,C++语⾔允许我们通过运算符重载的形式指定新的含义。

  • 运算符重载以后,其优先级和结合性与对应的内置类型运算符保持⼀致
  • 不能通过连接语法中没有的符号来创建新的操作符:⽐如operator@。 (.* :: sizeof ?: . 注意以上5个运算符不能重载。 )

如何定义及使用

运算符重载是具有特名字的函数,他的名字是由operator和后⾯要定义的运算符共同构成。和其他
函数⼀样,它也具有其返回类型和参数列表以及函数体 。

定义格式及使用

  • 重载运算符函数的参数个数和该运算符作⽤的运算对象数量⼀样多。
    • ⼀元运算符有⼀个参数。
    • ⼆元运算符有两个参数,⼆元运算符的左侧运算对象传给第⼀个参数,右侧运算对象传给第⼆个参数 。
  • 如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算
    符重载作为成员函数时,参数⽐运算对象少⼀个。

例如定义一个日期类的**+=**运算符(一元运算符):

Date& Date::operator+=(int day)
{
    _day += day;

    while (_day > GetMonthDay(_year, _month))
        {
            _day -= GetMonthDay(_year, _month);
            ++_month;
            if (_month == 13)
            {
                ++_year;
                _month = 1;
            }
        }

    return *this;
}

使用方法:d1 += 2;

流插入运算符重载(二元运算符):

ostream& operator<<(ostream& out, const Date& d)
{
    out << d._year << "年" << d._month << "⽉" << d._day << "⽇" << endl;
    return out;
}

使用方法: cout << d1;

前置++/后置++

重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,⽆法很好的区分。
C++规定,后置++重载时,增加⼀个int形参,跟前置++构成函数重载,⽅便区分。

前置++

前置递增运算符直接修改对象本身,并返回修改后的对象的引用。返回引用的原因是为了提高性能和节省内存。由于前置递增运算符直接修改对象,返回引用避免了不必要的对象拷贝。具体代码如下:

Date& Date::operator++()
{
    *this += 1; // 修改当前对象
    return *this; // 返回当前对象的引用
}

后置++

后置递增运算符需要返回修改前的对象,因此需要创建一个临时对象来保存递增前的状态。由于返回的是临时对象,不能返回引用。具体代码如下 :

Date Date::operator++(int)
{
    Date temp = *this; // 保存当前对象状态
    *this += 1; // 修改当前对象
    return temp; // 返回保存的临时对象
}

重载“<<” “>>”

重载<<>>时,需要重载为全局函数,因为重载为成员函数,this指针默认抢占了第⼀个形参位
置,第⼀个形参位置是左侧运算对象,调⽤时就变成了对象<<cout,不符合使⽤习惯和可读性。
重载为全局函数把ostream/istream放到第⼀个形参位置就可以了,第⼆个形参位置当类类型对
象。 友元函数没有this指针

// 流提取运算符重载
ostream& operator<<(ostream& out, const Date& d)
{

	out << d._year << "月" << d._month << "月" << d._day << "日" << endl;

	return out;
}


// 流插入运算符重载
istream& operator>>(istream& in, Date& d)
{
	cout << "请以此输入年月日 > ";
	in >> d._year >> d._month >> d._day;

	if (!d.CheckDate())
	{
		cout << "Date is error!" << endl;
	}

	return in;
}
// 在类中声明:
friend ostream& operator<<(ostream& out, const Date& d);
friend istream& operator>>(istream& in, Date& d);

(六)取地址运算符重载

const成员函数

const修饰成员函数的格式:void Print() const

作用:

  • 修饰this指针,加了const后表示函数内不能对类内任何成员进行修改。
  • 对于不用在内部修改的函数可以尽量加上const,这样在使用函数的时候不论是const类型还是普通类型的对象都可以正常使用,还可以保证数据的安全。

取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载。

如需重载取地址运算符,逻辑大体如下:
Date* operator&()
{
    return this;
    // return nullptr;
}


image.png

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

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

相关文章

Solana Blink和SEND的崛起:技术与市场效应的结合

随着Solana生态系统的不断发展&#xff0c;新的项目和技术不断涌现&#xff0c;吸引了大量的关注和投资。最近&#xff0c;Solana的Blink项目及其相关的SEND代币成为了市场的焦点&#xff0c;引发了广泛的讨论和投资热潮。本文将探讨Blink和SEND的技术创新、市场表现以及未来的…

大模型高效参数微调技术

文章目录 一、Fine-Tuning&#xff1a;微调二、Prompt-Tuning&#xff1a;提示调优2.1 工作原理2.2 PET (Pattern-Exploiting Training)2.3 Prompt-Tuning集成2.4 模板构建方式 三、Prefix Tuning&#xff1a;连续提示模板3.1 提出动机3.2 工作原理 四、P-Tuning V1/V24.1 P-Tu…

NFT如何解决音乐版权的问题

音乐版权问题一直困扰着音乐产业。传统的音乐版权管理模式存在以下问题。需要注意的是&#xff0c;NFT在音乐版权领域仍处于早期发展阶段&#xff0c;存在一些需要解决的问题&#xff0c;例如技术标准不统一、应用场景有限、法律法规不明朗等。但随着技术的进步和市场的完善&am…

【分库】分库的设计与原则、数据分片策略、垂直分库与水平分库、数据库引擎选择与配置优化

目录 引言 分库设计原则 数据分片策略的选择 垂直分库 vs 水平分库的比较 数据库引擎选择与配置优化 引言 在面对日益增长的数据量和不断升级的业务需求时&#xff0c;传统的单体数据库架构往往难以应对高并发、大数据量带来的性能瓶颈。为了突破这些限制&#xff0c;分库…

windows USB 设备驱动开发-USB 功能控制器驱动开发(二)

USB 功能客户端驱动程序使用的 UFX 对象和句柄 USB 函数类扩展 (UFX) 使用 WDF 对象功能来定义这些特定于 USB 的 UFX 对象。 重要的 API UfxDeviceCreateUfxEndpointCreate USB 函数类扩展 (UFX) 使用 WDF 对象功能来定义这些特定于 USB 的 UFX 对象。 这些对象是 WDF 对…

怎样优化 PostgreSQL 中对复杂条件筛选的执行效率?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 怎样优化 PostgreSQL 中对复杂条件筛选的执行效率&#xff1f;一、理解复杂条件筛选的挑战二、优化索引…

实现多层感知机

目录 多层感知机&#xff1a; 介绍&#xff1a; 代码实现&#xff1a; 运行结果&#xff1a; 问题答疑&#xff1a; 线性变换与非线性变换 参数含义 为什么清除梯度&#xff1f; 反向传播的作用 为什么更新权重&#xff1f; 多层感知机&#xff1a; 介绍&#xff1a;…

Linux: Mysql环境安装

Mysql环境安装&#xff08;Centos&#xff09; 前言一、卸载多余环境1.1 卸载mariadb1.2 查看并卸载系统mysql和mariadb安装包 二、换取mysql官方yum源三、安装并启动mysql服务3.1 yum源加载3.2 安装yum源3.3 安装mysql服务3.3.1 安装指令3.3.2 GPG密钥问题解决方法3.3.3 查看是…

LabVIEW液压数据采集测试系统

液压系统是装载机的重要组成部分&#xff0c;通过液压传动和控制实现各项作业功能&#xff0c;如提升、倾斜、转向等。液压系统的性能直接影响装载机的作业效率和稳定性。为了保证装载机液压系统的正常运行和优化设计&#xff0c;需要对其进行数据采集和测试。本文介绍了一套基…

Python酷库之旅-第三方库Pandas(022)

目录 一、用法精讲 55、pandas.lreshape函数 55-1、语法 55-2、参数 55-3、功能 55-4、返回值 55-5、说明 55-6、用法 55-6-1、数据准备 55-6-2、代码示例 55-6-3、结果输出 56、pandas.wide_to_long函数 56-1、语法 56-2、参数 56-3、功能 56-4、返回值 56-5…

Linux文件压缩与解压缩

在Linux中&#xff0c;tar实用程序是用于创建、管理和提取存档的常用命令。 tar实用程序的常用选项 执行tar操作需要以下tar命令操作之一&#xff1a; -c &#xff0c;--create &#xff1a;创建存档文件&#xff08;即压缩文件&#xff09;。-t&#xff0c;--list&#xff1…

0708,LINUX目录相关操作 + LINUX全导图

主要是冷气太足感冒了&#xff0c;加上少吃药抗药性差&#xff0c;全天昏迷&#xff0c;学傻了学傻了 01&#xff1a;简介 02&#xff1a; VIM编辑器 04&#xff1a;目录 05&#xff1a;文件 03&#xff1a;常用命令 06&#xff1a;进程 07&#xff1a;进程间的通信 cat t_c…

数据结构(4.1)——串的存储结构

串的顺序存储 串&#xff08;String&#xff09;的顺序存储是指使用一段连续的存储单元来存储字符串中的字符。 计算串的长度 静态存储(定长顺序存储) #define MAXLEN 255//预定义最大串为255typedef struct {char ch[MAXLEN];//每个分量存储一个字符int length;//串的实际长…

接口安全配置

问题点&#xff1a; 有员工在工位在某个接口下链接一个集线器&#xff0c;从而扩展上网接口&#xff0c;这种行为在某些公司是被禁止的&#xff0c;那么网络管理员如何控制呢&#xff1f;可以配置接口安全来限制链接的数量&#xff0c;切被加入安全的mac地址不会老化&#xff…

开源模型应用落地-工具使用篇-Spring AI-Function Call(八)

​​​​​​​一、前言 通过“开源模型应用落地-工具使用篇-Spring AI&#xff08;七&#xff09;-CSDN博客”文章的学习&#xff0c;已经掌握了如何通过Spring AI集成OpenAI和Ollama系列的模型&#xff0c;现在将通过进一步的学习&#xff0c;让Spring AI集成大语言模型更高阶…

Linux的世界 -- 初次接触和一些常见的基本指令

一、Linux的介绍和准备 1、简单介绍下Linux的发展史 1991年10月5日&#xff0c;赫尔辛基大学的一名研究生Linus Benedict Torvalds在一个Usenet新闻组(comp.os.minix&#xff09;中宣布他编制出了一种类似UNIX的小操作系统&#xff0c;叫Linux。新的操作系统是受到另一个UNIX的…

【Python】爬虫实战01:获取豆瓣Top250电影信息

本文中我们将通过一个小练习的方式利用urllib和bs4来实操获取豆瓣 Top250 的电影信息&#xff0c;但在实际动手之前&#xff0c;我们需要先了解一些关于Http 请求和响应以及请求头作用的一些知识。 1. Http 请求与响应 HTTP&#xff08;超文本传输协议&#xff09;是互联网上…

C#创建windows服务程序

步骤 1: 创建Windows服务项目 打开Visual Studio。选择“创建新项目”。在项目类型中搜索“Windows Service”并选择一个C#模板&#xff08;如“Windows Service (.NET Framework)”&#xff09;&#xff0c;点击下一步。输入项目名称、位置和其他选项&#xff0c;然后点击“创…

C++ | Leetcode C++题解之第232题用栈实现队列

题目&#xff1a; 题解&#xff1a; class MyQueue { private:stack<int> inStack, outStack;void in2out() {while (!inStack.empty()) {outStack.push(inStack.top());inStack.pop();}}public:MyQueue() {}void push(int x) {inStack.push(x);}int pop() {if (outStac…

秋招突击——7/9——MySQL索引的使用

文章目录 引言正文B站网课索引基础创建索引如何在一个表中查看索引为字符串建立索引全文索引复合索引复合索引中的排序问题索引失效的情况使用索引进行排序覆盖索引维护索引 数据库基础——文档资料学习整理创建索引删除索引创建唯一索引索引提示复合索引聚集索引索引基数字符串…