<C++>【类与对象篇】(二)

发布于:2022-12-29 ⋅ 阅读:(618) ⋅ 点赞:(0)

 

✨前言✨

🎓作者:【 教主 】

📜文章推荐:

☕博主水平有限,如有错误,恳请斧正。

📌机会总是留给有准备的人,越努力,越幸运!

💦导航助手💦


运算符重载

运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名以及参数列表,其返回值类型和参数列表与普通的函数类似。

函数名:关键字operator后面接需要重载的运算符符号。

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

注意:

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 不能改变其含义,例如操作符+,不能改变含义
  • .*  ::   sizeof  ?: 这五个运算符不能重载

创建一个日期类,对==操作符进行重载,如下:

class Date
	{
	public:
		Date(size_t year = 1, size_t month = 1, size_t day = 1)
		{
			_year = year;
			_month = month;
			_day = day;
		}
		bool operator==(const Date& d)
		{
			return d._day == _day && d._month == _month && d._year == d._year;
		}
	private:
		size_t _year;
		size_t _month;
		size_t _day;
	};

赋值运算符重载

  •  参数类型:const T& ,引用传参提高效率,加const保护T
  • 返回值类型:T&,返回引用提高效率,有返回值是为了连续传参
  • 检查是否给自己赋值
  • 返回*this
  • 赋值运算符重载只能重载为类的成员函数,不能作为全局函数,因为赋值运算符重载如果不显式实现,编译器会生成默认的,如果再定义一个全局的就会和默认的冲突。
  • 系统默认生成的是以值的方式逐字节拷贝,如果涉及内存资源管理,需要自己实现

前置++和后置++重载

日期类实现前置++和后置++

	class Date
	{
	public:
		Date(size_t year = 1, size_t month = 1, size_t day = 1)
		{
			_year = year;
			_month = month;
			_day = day;
		}
		Date& operator++()//前置++
		{
			_day++;
			return *this;
		}
		Date operator++(int)//后置++
		{
			Date temp(*this);
			_day++;
			return temp;
		}
	private:
		size_t _year;
		size_t _month;
		size_t _day;
	};
}

 C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递。

前置++使用引用返回,因为this指向的对象函数结束后不会销毁,引用传参效率高。后置++返回临时变量,不能使用引用传参。


初始化列表

初始化列表是以一个冒号开始,以逗号分隔的数据成员列表,每个成员变量后面跟一个放在括号中的初始值或者表达式。

class Date
	{
	public:
		Date(size_t year = 1, size_t month = 1, size_t day = 1)
			:_year(year)
			,_month(month),
			_day(day)
		{}
	private:
		size_t _year;
		size_t _month;
		size_t _day;
	};

注意 

  • 每个成员变量在初始化列表中只能出现一次
  • 类中的以下成员必须在初始化列表进行初始化
  1. 引用成员变量
  2. const成员
  3. 自定义类型成员
class A
	{
	public:
		A(int a=0)
			:_a(a)
		{}
	private:
		int _a;
	};
	class B
	{
	public:
		B(int a,int ref)
			:_aobj(a)
			,_ref(ref)
			,_n(1)
		{}
	private:
		A _aobj;
		int& _ref;
		const int _n;
	};
  • 尽量使用初始化列表进行初始化,因为自定义成员变量,先使用初始化列表进行初始化。
  • 成员变量在类中声明的次序是初始化列表中的初始化顺序, 与其在初始化列表中的先后次序无关

static成员

用static修饰的成员变量称为静态成员变量,成员函数称为静态成员函数,静态成员一定要在类外进行初始化

特性

  • 静态成员为所有类对象共享,不属于某个对象,存放在静态区
  • 静态成员类内声明,类外定义,定义时不添加static关键字
  • 类的静态成员可以用 类名::静态成员或者对象.静态成员来访问
  • 静态成员没有this指针,不能访问非静态成员
  • 静态成员受到访问限定符的限制

友元

友元提供了一种突破封装的方式,提供了便利,但突破封装又增加了风险,因此要少用。

友元函数

友元函数可以访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但是需要在类的内部声明,声明时需要加friend关键字

    void show(const Date& d)
	{
		cout << d._year << "-" << d._month << "-" << d._day << endl;
	}

	class Date
	{
		friend void show(const Date& d);
	public:
		Date(size_t year = 1, size_t month = 1, size_t day = 1)
		{
			_year = year;
			_month = month;
			_day = day;
		}
	private:
		size_t _year;
		size_t _month;
		size_t _day;
	};

注意 

  • 友元函数不是类的成员函数
  • 友元函数不能使用const修饰
  • 友元函数不受访问限定符的限制
  • 一个函数可以是多个类的友元函数
  • 调用与普通函数类似

友元类

友元类的所有成员函数都可以是另一个类的友元函数,可以访问另一个类的非公有成员

注意

  • 友元关系是单向的,不具有交换性。"你是我的朋友,但我不是你的朋友"
  • 友元关系不能传递
  • 友元不能继承

内部类

如果一个类定义在类的内部,这个类就叫做内部类,内部类是一个独立的类,不属于外部类,不能通过外部类的对象访问内部类的成员,外部类对内部类没有访问权限。但是,内部类是外部类的友元。

特性:

  • 内部类的定义不受访问限定符的限制
  • 内部类可以直接访问外部类的static成员,不需要外部类的对象/类名
  • sizeof(外部类)=外部类,与内部类无关

欢迎关注,码字不易,希望多多点赞、收藏哦!抱拳了。

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到