C++——类和对象之运算符重载

news2024/11/29 4:39:22

运算符重载

本章思维导图:

在这里插入图片描述

注:本章思维导图对应的xmind文件和.png文件都已同步导入至”资源“


文章目录

  • 运算符重载
    • @[toc]
  • 1. 运算符重载的意义
  • 2. 函数的声明
    • 2.1 声明运算符重载的注意事项
  • 3. 函数的调用
  • 4. const成员函数
    • 4.1 const成员函数的声明
    • 4.2 注意点
  • 5. 两个默认成员函数
    • 5.1 赋值运算符重载
      • 5.1.1 函数的声明
      • 5.1.2 函数的定义
      • 5.1.3 赋值运算符重载和拷贝构造的区别
      • 5.1.4 默认赋值运算符重载
    • 5.2 &和const &运算符重载
  • 6. 流插入<<、流提取>>运算符重载
    • 6.1 函数的声明
  • 7. Date类的实现
    • 7.1 对于部分代码的说明

1. 运算符重载的意义

我们都知道,对于内置类型我们是可以直接用运算符直接对其进行操作的,但是对于自定义类型,这种做法是不被允许的

例如对于Date类:

Date d1;
Date d2(2023, 11, 3);

d1 == d2;
//会报错:error C2676: 二进制“==”:“Date”不定义该运算符或到预定义运算符可接收的类型的转换

因此,为了解决自定义类型不能使用操作符的问题,C++就有了运算符重载

2. 函数的声明

在这里插入图片描述

一般来说,运算符重载的函数最好声明在类里面,这样就可以使用被private修饰的成员变量

声明方式:

operator 运算符 形参列表

  • 函数的返回值应该和运算符的意义相对应。例如对于比较运算符>、==就应该返回bool值,对于+、-就应该返回当前类类型
  • 函数的形参个数应该和运算符的操作数相对应

例如,我们要声明定义一个Date += 整数的函数,那我们就要重载运算符+=

//根据+=运算符的意义,其返回值应该是操作数本身,因此返回其引用
Date& operator +=(int day)
{
    //仅作为运算符重载如何声明定义的演示
    //实现细节先不做说明

    return *this;
}

2.1 声明运算符重载的注意事项

有小伙伴可能注意到:为什么Date& operator +=(int day)的形参只有一个day,不是说形参个数要和运算符的操作数对应吗?

我们不能忘记:在类的成员函数中,都有一个默认的形参this指针来指向当前的对象

同时还应该注意以下几点:

  • 不能通过连接其他符号来实现重载,例如operator @()是不被允许的
  • 不能修改内置类型运算符的意义
  • .* . :? sizeof ::这五个运算符是不可以重载的
  • 对于二元运算符(操作数为2的运算符),形参列表的第一个参数为左操作数,第二个参数为右操作数。因此对于声明在类里面的重载函数,this指针永远是左操作数

3. 函数的调用

在这里插入图片描述

在声明定义好运算符重载后,有两种调用方法:

第一种——像内置类型一样直接使用运算符

d1 += 10;
//调用Date& operator +=(int day)函数,在对象d1的基础上加10

第二种——像调用函数一样,使用运算符重载

d1.operator+=(10);
//调用Date& operator +=(int day)函数,在对象d1的基础上加10

4. const成员函数

在这里插入图片描述

我们来看下面的代码:

class Date
{
public:
	Date(int year = 2023, int month = 11, int day = 3)
    {
         //简单的值拷贝
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }

	void Print()
	{
		cout << _year << ';' << _month << ' ' << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	const Date d2;

	d1.Print();		//Yes
	d2.Print();		//Not

	return 0;
}
//d2.Print()会报错:不能将“this”指针从“const Date”转换为“Date &”

这是因为:

我们之前提到过,引用不能涉及到权限的放大const Date d2对应的是const Date* this,而函数Print里的默认的是Date* this,这就涉及到了权限的放大。

因此,为了解决被const修饰的对像不能调用成员函数的问题,我们可以用const来修饰成员函数,这样,本质上成员函数的this指针就被const修饰了,从而也就可以被const对象调用。

4.1 const成员函数的声明

将一个成员函数变为const成员函数,只要在该函数声明的最后加上const修饰符即可

例如对于上面提到的Pinrt()成员函数,将其变为const成员函数即:

void Print() const
{
    cout << _year << ';' << _month << ' ' << _day << endl;
}

4.2 注意点

应该知道,引用不能涉及权限的放大,但是可以进行权限的平移和缩小。

因此:

  • const对象可以调用const成员函数
  • 非const对象也可以调用const成员函数

并不能说可以将所有的成员函数都声明为const成员函数,因为对于有些成员函数,它需要在函数内部修改对象的成员变量。

但是对于那些不需要修改对象成员变量的成员函数,建议都将其声明为cosnt,这样const对象和非const对象都能调用

5. 两个默认成员函数

运算符重载中也有两个成员函数,分别是:赋值=运算符重载和取地址&\const &运算符重载

5.1 赋值运算符重载

赋值运算符重载是类的默认成员函数

在这里插入图片描述

5.1.1 函数的声明

  • 因为赋值运算符重载是类的默认成员函数,因此必须声明在类的里面
  • =运算符的操作对象为2,因此该函数有两个形参。第一个形参为被隐藏的this指针,第二个形参就是要赋予值的对象,且该对象最好被const修饰
  • 为了支持连续赋值,函数的返回值应该是类类型的引用

例如,声明一个Date类的赋值运算符重载:

Date& operator=(const Date& d)
{
 	//
}

5.1.2 函数的定义

应该清楚,赋值实际上也是一种拷贝。而拷贝又分为深拷贝和浅拷贝:

浅拷贝:

  • 浅拷贝又称值拷贝
  • 浅拷贝只是对成员变量值的简单复制,而不是复制指向的动态分配的资源(如堆内存)
  • 原对象和拷贝对象将共享相同的资源

深拷贝:

  • 深拷贝又称址拷贝
  • 相较于浅拷贝只是对成员变量值的简单赋值,深拷贝会复制对象的成员变量以及指向的资源,包括指针指向的数据
  • 这确保了原对象和拷贝对象拥有彼此独立但内容相同的资源副本

关于深浅拷贝更为清楚的解释请移步👉C++——拷贝构造

既然拷贝分为深浅拷贝,那么我们的赋值运算符重载也应该分为值拷贝、址拷贝这两种情况:

值拷贝:

例如对于Date类,里面没有指针指向空间资源,因此只需要对其成员变量进行简单复制操作

Date& operator=(const Date& d)
{
 //简单的值拷贝
 _year = d._year;
 _month = d._month;
 _day = d._day;

 return *this;
}

址拷贝:

例如对于Stack类,里面有一个指针用于指向栈存储的空间,因此需要进行深拷贝来创建一个和源对象内容相同但地址不同的空间

Stack& operator=(const Stack& st)
{
 _capacity = st._capacity;
 _top = st._top;

 //深拷贝
 _a = (int*)malloc(sizeof(int) * _capacity);
 if (nullptr == _a)
 {
     perror("malloc");
     exit(-1);
 }
 memcpy(_a, st._a, sizeof(int) * _capacity);

 return *this;
}

5.1.3 赋值运算符重载和拷贝构造的区别

看完上面函数的定义,有小伙伴就肯定会有疑惑了:

这看起来二者之间没有什么区别嘛,为什么要做区分?

我们来看下面的例子:

class Date
{
public:
    //构造
	Date(int year = 2023, int month = 11, int day = 3)
	{
        _year = year;
        _month = month;
        _day = day;
	}
	//拷贝构造
	Date(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
	}
	//赋值运算符重载
	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;

		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
	Date d2 = d1;	//拷贝构造还是赋值运算符重载???
    
	Date d3;
	d3 = d2;	//拷贝构造还是赋值运算符重载???

	return 0;
}

各位认为,上面问题的答案是什么?让我们来进行调试:

在这里插入图片描述

可以得出结论:赋值运算符重载和拷贝构造的不同之处在于:

  • 拷贝构造注重的是构造,即用一个已经存在的对象来实例化构造一个新的对象
  • 赋值运算符重载注重的是赋值,即对两个已经存在的对象进行赋值操作

5.1.4 默认赋值运算符重载

和其他默认成员函数一样,如果自己没有声明和定义赋值运算符重载,编译器会自动生成一个

和拷贝构造一样,默认运算符重载只会对成员变量进行简单的值拷贝(浅拷贝),因此如果类的成员变量有指向内存空间的指针,仅依赖系统默认生成的赋值运算符重载是不够的,需要自己声明定义,来实现深拷贝

5.2 &和const &运算符重载

这两个函数都是类的默认成员函数

  • 他们的作用仅用于返回对象的地址
Date* operator&()
{
    return this;
}

const Date* operator&() const
{
    return this;
}

这两个默认成员函数一般用编译器自动生成的默认&运算符重载即可,不需要自己声明和定义

6. 流插入<<、流提取>>运算符重载

在这里插入图片描述

通过查阅资料我们可以得知:coutostream类的对象,cinistream类的对象

extern ostream cout;
extern istream cin;

6.1 函数的声明

我们可以先看一个例子来推出这两个重载函数的返回值是什么:

cout << 10 << 20;

这串代码实现的是向屏幕连续输出两个数字10和20<<运算符的运算顺序应该是从左到右,而为了能够实现连续的cout,我们可以假象在执行完cout << 10后有生成了一个cout来完成cout << 20

在这里插入图片描述

而为了能够实现执行完cout << 10后又生成一个coutcout运算符重载的返回值就应该是ostream类的引用,即ostream &

同理,cin运算符重载的返回值就应该是istream &

接下来的问题是,这两个运算符重载应该放在类里面还是类外面呢?

如果声明在类里面:

class Date
{
public:
 //构造
	Date(int year = 2023, int month = 11, int day = 3)
	{
     _year = year;
     _month = month;
     _day = day;
	}

	ostream& operator<<(ostream& _cout)
	{
		_cout << _year << ' ' << _month << ' ' << _day << endl;

		return _cout;
	}
private:
	int _year;
	int _month;
	int _day;
};

那当我们使用时:

int main()
{
	Date d1;
	cout << d1;

	return 0;
}
//就会报错:二元“<<”: 没有找到接受“Date”类型的右操作数的运算符(或没有可接受的转换)

这是因为,我们在前面就说过,对于二元运算符,第一个形参就是左操作数,第二个形参就是右操作数。而对于类的成员函数,this指针就是第一个参数,即左操作数。因此对于流插入运算符<<,左操作数就是d1,右操作数就是_cout

正确的写法应该为:

d1 << cout;

显然,这种写法的可读性是极差的。我们**应该想办法使_cout成为左操作数,this指针成为右操作数,**但是对于类的成员函数,形参的第一个都必定是指向对象的this指针,所以,为了达到要求,我们应该将<<>>运算符的重载声明定义在类的外面

即:

class Date
{
public:
 //构造
	Date(int year = 2023, int month = 11, int day = 3)
	{
     _year = year;
     _month = month;
     _day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << ' ' << d._month << ' ' << d._day << endl;

	return _cout;
}

我们将<<>>运算符的重载声明在类外面,可读性的问题是解决了,但是这样就访问不了被private修饰的成员变量了呀。

为了解决这个问题,我们可以使用友元函数friend

将非类成员函数的函数声明放在类里面,再在声明前面加上修饰符friend,这样这个函数就变成了友元函数。

  • 友元函数不是类的成员函数
  • 但是可以直接访问类的私有成员

例如,对于上面的代码:

class Date
{
public:
    //构造
	Date(int year = 2023, int month = 11, int day = 3)
	{
        _year = year;
        _month = month;
        _day = day;
	}
    
    friend ostream& operator<<(ostream& _cout, const Date& d);

private:
	int _year;
	int _month;
	int _day;
};

ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout << d._year << ' ' << d._month << ' ' << d._day << endl;

	return _cout;
}

这样,我们就可以正确使用<<>>运算符重载了。

7. Date类的实现

class Date
{
public:
	// 获取某年某月的天数
	int GetMonthDay(int year, int month)
	{
		int nums[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

		if (month == 2 && (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)))
			return nums[month] + 1;
		else
			return nums[month];
	}

	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1)
	{
		if (year < 1 || month < 1 || month > 12 || day < 1 || day > GetMonthDay(year, month))
		{
			cout << "输入非法" << endl;
			exit(-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;
	}

	// 日期+=天数
	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)
			{
				_month = 1;
				_year++;
			}
		}

		return *this;
	}

	// 日期+天数
	Date operator+(int day)
	{
		Date tmp = *this;
        
		tmp += day;

		return tmp;
	}

	// 日期-天数
	Date operator-(int day)
	{	
		Date tmp = *this;

		tmp -= day;

		return tmp;
	}

	// 日期-=天数
	Date& operator-=(int day)
	{
		if (day < 0)
			return *this += (-day);
		
		_day -= day;

		while (_day < 1)
		{
			_month--;
			if (_month <= 0)
			{
				_month = 12;
				_year--;
			}

			_day += GetMonthDay(_year, _month);
		}

		return *this;
	}

	// 前置++
	Date& operator++()
	{
		*this += 1;
		return *this;
	}

	// 后置++
	Date operator++(int)
	{
		Date tmp = *this;
		*this += 1;

		return tmp;
	}

	// 后置--
	Date operator--(int)
	{
		Date tmp = *this;
		*this -= 1;

		return tmp;
	}

	// 前置--
	Date& operator--()
	{
		*this -= 1;
		return *this;
	}

	// >运算符重载
	bool operator>(const Date& d)
	{
		if (_year > d._year)
			return true;
		else if (_year == d._year && _month > d._month)
			return true;
		else if (_year == d._year && _month == d._month && _day > d._day)
			return true;
		else
			return false;
	}

	// ==运算符重载
	bool operator==(const Date& d)
	{
		return _year == d._year && _month == d._month && _day == d._day;
	}

	// >=运算符重载
	bool operator >= (const Date& d)
	{
		return (*this == d) || (*this > d);
	}

	// <运算符重载
	bool operator < (const Date& d)
	{	
		return !(*this >= d);
	}


	// <=运算符重载
	bool operator <= (const Date& d)
	{
		return (*this == d) || (*this < d);
	}


	// !=运算符重载
	bool operator != (const Date& d)
	{
		return !(*this == d);
	}


	// 日期-日期 返回天数
	int operator-(const Date& d)
	{
		int flag = 1;
		if (!(*this >= d))
			flag = -1;

	    Date cmp_big = *this >= d ? *this : d;
		Date cmp_small = *this < d ? *this : d;
		int count = 0;

		while (cmp_big != cmp_small)
		{
			count++;
			++cmp_small;
		}

		return flag * count;
	}

	// 析构函数
	~Date()
	{
		//cout << "~Date()" << endl;
	}


private:
	int _year;
	int _month;
	int _day;
};

7.1 对于部分代码的说明

  1. 注意代码的复用,这样可以少些许多代码,提高效率。

    例如:定义好+=、-=的运算符重载后,-、+运算符的重载就可以复用+=、-=的代码;定义好==、>的运算符重载后,其他比较运算符就可以复用==、>的运算符重载来实现,从而大幅减少了代码量。

  2. 注意前置++和后置++的运算符重载(前置--和后置--同理)

    由于C++规定,要构成运算符重载,运算符必须跟在operator后,因此当碰到前置++和后置++这种运算符相同(函数名相同)但函数实现的功能不同的情况时,就需要利用函数重载。我们可以在后置++的运算符重载函数的形参列表里加入一个形参,和前置++构成函数重载,这样就可以避免问题了。

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

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

相关文章

C++查漏补缺与新标准(C++20,C++17,C++11)02 C++快速回顾(二)

本内容参考C20高级编程 C风格的数组 //形如 int myArray[3]{2};一个比较新颖的获取C风格数组大小的函数std::size()&#xff0c;返回size_t类型&#xff08;在中定义的无符号整数&#xff09; #include <iostream> using namespace std;int main() {int myArray[5] {…

UML---用例图

UML–用例图 0.用例图简介 用例图是一种UML&#xff08;统一建模语言&#xff09;的图形化表示方法&#xff0c;用于描述系统的功能和行为。它可以帮助系统分析师和开发人员理解系统的需求&#xff0c;用例图由参与者、用例和它们之间的关系组成。 1.用例图的组成部分 系统…

【RabbitMQ】RabbitMQ 消息的可靠性 —— 生产者和消费者消息的确认,消息的持久化以及消费失败的重试机制

文章目录 前言&#xff1a;消息的可靠性问题一、生产者消息的确认1.1 生产者确认机制1.2 实现生产者消息的确认1.3 验证生产者消息的确认 二、消息的持久化2.1 演示消息的丢失2.2 声明持久化的交换机和队列2.3 发送持久化的消息 三、消费者消息的确认3.1 配置消费者消息确认3.2…

订单业务和系统设计(一)

一、背景简介 订单其实很常见&#xff0c;在电商购物、外卖点餐、手机话费充值等生活场景中&#xff0c;都能见到它的影子。那么&#xff0c;一笔订单的交易过程是什么样子的呢&#xff1f;文章尝试从订单业务架构和产品功能流程&#xff0c;描述对订单的理解。 二、订单业务…

飞书开发学习笔记(二)-云文档简单开发练习

飞书开发学习笔记(二)-云文档简单开发练习 一.云文档飞书开发环境API 首先还是进入开放平台 飞书开放平台&#xff1a;https://open.feishu.cn/app?langzh-CN 云文档相关API都在“云文档”目录中&#xff0c;之下又有"云空间",“文档”&#xff0c;“电子表格”&a…

LLM系列 | 26:阿里千问Qwen模型解读、本地部署

引言 简介 预训练 数据来源 预处理 分词 模型设计 外推能力 模型训练 实验结果 部署实测 对齐 监督微调(SFT) RM 模型 强化学习 对齐结果(自动和人工评估) 自动评估 人工评估 部署实测 总结 引言 人生自是有情痴&#xff0c;此恨不关风与月。 ​ 今天这篇小…

从零开始:开发你的第一个抖音小程序

抖音小程序提供了独特的机会&#xff0c;能够让你将自己的创意和内容传播给数百万的抖音用户。本文将带你走一趟开发抖音小程序的旅程&#xff0c;从零开始&#xff0c;无需编程经验。你将了解到如何准备开发环境、创建你的第一个小程序&#xff0c;以及如何将它发布到抖音平台…

辅助驾驶功能开发-功能规范篇(22)-9-L2级辅助驾驶方案功能规范

1.3.7.2 行人、骑行者(横向)AEB 系统 1.3.7.2.1 状态机 1.3.7.2.2 信号需求列表 同 1.3.2.1.2。 1.3.7.2.3 系统开启关闭 同 1.3.2.1.3。 触发横向 AEB 的目标包括横向运动的行人、骑行者(包括自行车、摩托车、电瓶车和平衡车上的行人)。 1.3.7.2.4 制动预填充 制动系统…

Global-aware siamese network for change detection on remote sensing images

遥感图像中的变化检测是以有效的方式识别观测变化的最重要的技术选择之一。CD具有广泛的应用&#xff0c;如土地利用调查、城市规划、环境监测和灾害测绘。然而&#xff0c;频繁出现的类不平衡问题给变化检测应用带来了巨大的挑战。为了解决这个问题&#xff0c;我们开发了一种…

Spring Boot 整合SpringSecurity和JWT和Redis实现统一鉴权认证

&#x1f4d1;前言 本文主要讲了Spring Security文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日一句&#xff1a;努力…

VPN网络环境下 本地客户端能连上mysql 本地启服务连不上mysql的原因

背景 公司mysql使用的是华为云RDS&#xff0c;由于要做一些测试验证&#xff0c;需要本地通过VPN直连华为RDS节点&#xff1b;找运维配置好网络后&#xff0c;本地 telnet 内网ip 3306 以及通过navicat客户端都能正常连接数据库&#xff1b;但是本地启动的服务就是连接不上。问…

【PyQt学习篇 · ⑩】:QAbstractButton的使用

文章目录 QAbstractButton简介子类化抽象类图标设置快捷键设置自动重复状态设置排他性点击设置点击有效区域可用信号 QAbstractButton简介 QAbstractButton 是一个抽象类&#xff0c;无法直接实例化&#xff0c;但它提供了很多在 PyQt 中使用按钮时常用的功能和特性。开发人员…

c++ 实现 AVL 树

AVL 树的概念 二叉搜索树虽可以缩短查找的效率&#xff0c;但如果数据有序或接近有序二叉搜索树将退化为单支树&#xff0c;查找元素相当于在顺序表中搜索元素&#xff0c;效率低下。因此&#xff0c;两位俄罗斯的数学家 G.M.Adelson-Velskii 和 E.M.Landis 在 1962 年发明了一…

实现Git增量代码的Jacoco覆盖率统计

今天我们给大家分享&#xff0c;如何使用Jacoco集合Git来做增量代码的覆盖率测试。实现的基本原理是&#xff1a; 使用Git的diff指令&#xff0c;计算出两个版本的差异&#xff1b;改造Jacoco源代码&#xff0c;只针对增量代码生成报告。 基本的功能滴滴的super-jacoco项目已…

使用Selenium IDE录制脚本

今天&#xff0c;我们开始介绍基于开源Selenium工具的Web网站自动化测试。 Selenium包含了3大组件&#xff0c;分别为&#xff1a;1. Selenium IDE 基于Chrome和Firefox扩展的集成开发环境&#xff0c;可以录制、回放和导出不同语言的测试脚本。 2. WebDriver 包括一组为不同…

2023年道路运输企业主要负责人证考试题库及道路运输企业主要负责人试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年道路运输企业主要负责人证考试题库及道路运输企业主要负责人试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人…

助力企业数智化转型,网易数帆是这样做的

伴随着云计算、大数据、人工智能等新兴技术的飞速发展&#xff0c;数字经济在国民经济中的重要性也变得愈发凸显。席卷全球的数字化和智能化浪潮不但深切地改变了人们的工作和生活方式&#xff0c;而且也给企业和组织带来了全新的发展机遇。 然而在数智化转型升级的道路上&…

免费外文文献检索网站,你一定要知道

01. Sci-Hub 网址链接&#xff1a;https://tool.yovisun.com/scihub/ Sci-hub是一个可以无限搜索、查阅和下载大量优质论文的数据库。其优点在于可以免费下载论文文献。 使用方法&#xff1a; 在Sci—hub搜索栏中粘贴所需文献的网址或者DOI&#xff0c;然后点击右侧的open即可…

分库分表自定义路由组件

1. 定义路由注解 Documented Retention(RetentionPolicy.RUNTIME) // Target用来表示注解作用范围&#xff0c;超过这个作用范围&#xff0c;编译的时候就会报错。 // Target(ElementType.TYPE)——接口、类、枚举、注解,Target(ElementType.METHOD)——方法 Target({Elem…

【Qt之事件过滤器】使用

介绍 事件过滤器是Qt中一种重要的机制&#xff0c;用于拦截并处理窗口和其他对象的事件。 它可以在不修改已有代码的情况下&#xff0c;动态地增加、删除一些处理事件的代码&#xff0c;并能够对特定对象的事件进行拦截和处理。 在Qt中&#xff0c;事件处理经过以下几个阶段&…