类与对象(3)

1.运算符重载

在上一篇博客中6个默认的成员函数,其中拷贝赋值中的赋值重载就是运算符重载。

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

函数名:operator加上需要重载运算符(比如:operator+)

函数:返回值类型  operator加上运算符(参数)

注意:

  • 不能通过连接其他符号来创建新的操作符,必须是C++规定的运算符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义最好不要改变,例如:内置的整数-,就是“减”的含义,不要把它写成“加”。
  • 作为类成员函数重载时,其形参看起来比操作数数目少一个,因为成员函数第一个参数为隐藏的this
  • .*    : :    sizeof    ?:    .   以上5个运算符不能重载。
class Date
{
public:
	Date(int year = 2024, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
//private:
	int _year;
	int _month;
	int _day;
};
//重载为全局,无法访问私有成员,所以以下函数会报错
//解决方法:1、提供成员get、set
//         2、友元(后面才会学习)
//         3、重载成员函数
//
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(2024, 1, 3);
	Date d2(2024, 2, 3);

	//显式调用
	operator==(d1, d2);

	//直接写,转换调用,编译器会自动转换成operator==(d1, d2);
	d1 == d2;
}

类成员重载:

class Date
{
public:
	Date(int year = 2024, 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 this->_year == d2._year
		&& this->_month == d2._month
			&& this->_day == d2._day;//this->可以不加,会自动生成
	}
private:
	int _year;
	int _month;
	int _day;
};

1.1赋值运算符重载

赋值运算符重载是一个默认函数,用于完成两个已经存在的对象进行拷贝。

赋值运算符重载是一个运算符重载,规定必须重载为成员函数。

  • 参数类型:传递引用可以提高传参效率(减少拷贝构造)
  • 返回值类型:返回引用可以提高返回的效率(同样是减少拷贝构造)有返回值的目的是为了支持连续赋值场景。
  • 没有显示实现时,会自动生成默认的赋值运算符重载,跟默认构造函数类似,对内置类型完成值拷贝/浅拷贝(一个一个字节拷贝),对于自定义类型会调用他的拷贝构造
  • 实践中总结:

    1、如果没有管理资源,编译器自动生成的赋值重载就可以。如Date。

    2,、如果都是自定义成员,内置成员也没有资源管理,默认生成的赋值重载就可以。如MyQueue。

    3、一般情况下,不需要写析构函数就是不需要写赋值重载。

首先先区分拷贝构造赋值拷贝(赋值重载)

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

}


Date d1(2024, 3, 5);
Date d2 = d1;//这是拷贝构造,1个已经存在的对象,拷贝给另一个要创建的初始化的对象

Date d4(2024, 4, 6);
d1 = d4;//这是赋值拷贝,2个都存在的对象,拷贝赋值给另一个已经存在的对象

上面的例子是单个赋值,如果连续复制呢?

怎么拿到d2,然后再把d2给到d1?

//d1=d2=d4;
Date& operator=(const Date& d)//d是d4的别名
{
		_year = d._year;
		_month = d._month;
		_day = d._day;

		return *this;//this是d2的指针,*this就代表d2(第一轮赋值)
}

2.取地址运算符重载

2.1const成员函数

  • 用const修饰的成员函数叫做const成员函数,const放在函数参数列表后面。比如:bool operator==(const Date& d) const;

    首先,先分清楚一个概念:

    const在*左边修饰的是指针所指向的内容,代表不能通过指针来改变指针指向的内容。而指针变量本身内容可变。

    int main()
    {
    	int a = 1;
    	int b = 2;
    
    	const int* p = &a;//int const* p = &a;
    	p = &b;//p指针本身所指内容可以改变
    	*p = 10;//报错->p指针所指向的内容不能改变
    
    	return 0;
    }

    const在*右边修饰的是指针变量本身,代表不能改变指针变量本身的内容。而指针变量所指向的内容可以改变。

    int main()
    {
    	int a = 1;
    	int b = 2;
    	
    	int* const p = &a;
    	p = &b;//报错->p本身内容不可改变
    	*p = 12;//p所指向的内容可改变
    
    	return 0;
    }
  • const实际修饰所指成员函数的this指针,表明在该成员函数中不能对类中任何成员进行修改。
  •  改成这样才正确:

2.2取地址运算符重载

取地址运算符重载分为普通取地址运算符重载和const取地址运算符重载,一般我们直接用编译器自动实现的就可以了,除非我们不想让别人知道当前类对象的地址,可以自己显式实现,随便返回一个地址。

class Date
{
public :
    Date* operator&()
    {
        return this;
        // return nullptr;//返回0000
    }
    const Date* operator&()const
    {
        return this;
        // return nullptr;
    }
    Date* operator&()
    {
        return (Date*)0x3478GH23;//胡乱返回一个地址
    }
        
private :
    int _year ;
    int _month ; 
    int _day ;
};

 3.类型转换

  • C++支持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数。
  • 构造函数前加explicit就不支持隐式类型转换。

class B
{
public :
	//explicit B(int b);不能用隐式构造
	B(int b)
	{
		_b = b;
	}

	void Print()
	{
		cout << _b << endl;
	}

private:
	int _b;
};

int main()
{
	//隐式类型转换
	B b1 = 2;
	b1.Print();

	return 0;
}
  •  普通类型
  • 引用类型
  • C++11还支持多参数转化
class B
{
public :
	//explicit B(int b);不能用隐式构造
	B(int b, int c)
	{
		_b = b;
        _c = c;
	}

	void Print()
	{
		cout << _b << _c << endl;
	}

private:
	int _b;
    int _c;
};

int main()
{
	//隐式类型转换
	B b1 = {3, 4};
	b1.Print();

	return 0;
}

over~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值