类和对象(下)(二)

类和对象(下)(二)

  • 1.友元
    • 1.1友元函数
    • 1.2友元类
  • 2.内部类
  • 3.拷贝对象时的一些编译器优化(vs2022)

hello,各位读者大大们你们好呀
系列专栏:【C++的学习】
本篇内容:友元;内部类;拷贝对象时的一些编译器优化(vs2022)
⬆⬆⬆⬆上一篇:类和对象(下)(一)
作者简介:轩情吖,请多多指教(> •̀֊•́ ) ̖́-

1.友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏封装,所以说友元不宜多用。
友元分为:友元函数和友元类

1.1友元函数

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

#define _CRT_SECURE_NO_WARNINGS 1
#include 
using namespace std;
class Date
{
friend void Print(Date& d);//声明友元函数
public:
	Date(int year=1, int month=1, int day=1)
		:
		_day(day),
		_year(year),
		_month(month)
	   {}
private:
	int _year;
	int _month;
	int _day;
};
void Print(Date& d)
{
	cout << d._year << "-" << d._month << "-" << d._day << endl;//可以直接突破类的访问限定符
}
int main()
{
	Date d1(2023, 2, 13);
	Print(d1);
	return 0;
}

说明:
友元函数可以访问类的私有和保护成员,但不是类的成员函数
友元函数不能用const修饰
友元函数可以在类定义的任何地方声明,不受访问限定符的限制
一个函数可以是多个类的友元函数
友元函数的调用与普通函数的调用原理相同

1.2友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
友元关系是单向的,不具有交换性
友元关系不能传递
如果C是B的友元,B是A的友元,则不能说明C是A的友元
友元关系不能继承

#define _CRT_SECURE_NO_WARNINGS 1
#include 
using namespace std;
class Time
{
	friend class Date;//友元类
public:
	Time(int hour=0, int minute=0, int second=0)
		:_hour(hour),
		_minute(minute),
		_second(second)
	{}
private:
	int _hour;
	int _minute;
	int _second;
};

class Date
{
public:
	Date(int year=0,int month=0,int day=0)
		:_year(year),
		_month(month),
		_day(day),
		_t(15,2,10)
	{}
	void Print()
	{
		cout << _t._hour << ":" << _t._minute << ":" << _t._second << endl;//可以突破访问限定符访问
	}

private:
	int _year;
	int _month;
	int _day;
	Time _t;
};
int main()
{
	Date().Print();
	return 0;
}

2.内部类

概念:如果一个类定义在另一个类的内部,这个类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限,只是受外部类的类域限制

#define _CRT_SECURE_NO_WARNINGS 1
#include 
using namespace std;
class Date
{
public:
	Date(int year=0,int month=0,int day=0)
		:_year(year),
		_month(month),
		_day(day)
	{}
	class Time
	{
	public:
		Time(int hour = 0, int minute = 0, int second = 0)
			:_hour(hour),
			_minute(minute),
			_second(second)
		{}
	private:
		int _hour;
		int _minute;
		int _second;
	};
private:
	int _year;
	int _month;
	int _day;
};
int main()
{



	return 0;
}

注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问类中的所有成员。但是外部类不是内部类的友元。

#define _CRT_SECURE_NO_WARNINGS 1
#include 
using namespace std;
class Date
{
public:
	Date(int year=0,int month=0,int day=0)
		:_year(year),
		_month(month),
		_day(day)
	{}
	class Time
	{
	public:
		Time(int hour = 0, int minute = 0, int second = 0)
			:_hour(hour),
			_minute(minute),
			_second(second)
		{}
		void Print(const Date& d)
		{
			cout << d._year << "-" << d._month << "-" << d._day << endl;//内部类是外部类的友元
		}
	private:
		int _hour;
		int _minute;
		int _second;
	};
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d(2023, 2, 13);
	Date::Time().Print(d);//Time受Date的类域限制

	return 0;
}

特性:
①内部类可以定义在外部类的public、protected、private都是可以的
②注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名

#define _CRT_SECURE_NO_WARNINGS 1
#include 
using namespace std;
class Date
{
public:
	Date(int year=0,int month=0,int day=0)
		:_year(year),
		_month(month),
		_day(day)
	{}
	class Time
	{
	public:
		Time(int hour = 0, int minute = 0, int second = 0)
			:_hour(hour),
			_minute(minute),
			_second(second)
		{}
		static int  Print()
		{
			return count;
		}
	private:
		int _hour;
		int _minute;
		int _second;
	};
private:
	static int count;
	int _year;
	int _month;
	int _day;
};
int Date::count = 20;
int main()
{
	cout << Date::Time::Print() << endl;//Time受Date的类域限制

	return 0;
}

③sizeof(外部类)=外部类,和内部没有任何关系
类和对象(下)(二)_第1张图片
依旧用的是上一个代码

3.拷贝对象时的一些编译器优化(vs2022)

在传参和传返回值的过程中,一般编译器会做一些优化,减少对象的拷贝,这个在一些场景下还是非常有用的。

#define _CRT_SECURE_NO_WARNINGS 1
#include 
using namespace std;
class Date
{
public:
	Date(void)
		:_year(0),
		_month(0),
		_day(0)
	{
		cout << "构造函数" << endl;
	}

	Date(int i)
	{
		cout << "带参数的构造函数" << endl;
	}

	~Date(void)
	{
		cout << "析构函数" << endl;
	}
	Date(const Date& d)
		:_year(d._year),
		_month(d._month),
		_day(d._day)
	{
		cout << "拷贝构造函数" << endl;
	}
	Date& operator=(const Date& d)
	{
		cout << "赋值运算符重载" << endl;
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	}
private:
	int _year;
	int _month;
	int _day;
};

void func(Date d)
{}
void func1(const Date& d)
{}
Date fun2(void)
{
	Date a;
	return a;
}
Date func3(void)
{
	return Date();
}
int main()
{
	//Date()._year = 1;//匿名对象是常量
	
	/*Date d1;
	func(d1);//构造+拷贝构造
	*/
	
	//func(Date());//构造+拷贝构造->构造

	//func(1);//构造+拷贝构造->构造
//
	/*Date d1;
	func1(d1);//构造
	*/

   //func1(Date());//构造

	//func1(1);//构造
///
	//fun2();//构造+拷贝构造

	//Date d=fun2();//构造+拷贝构造+拷贝构造->构造+拷贝构造(这里的构造是上面函数里一开始a的构造函数)

	//func3();//构造+拷贝构造->构造

	//Date d=func3();//构造+拷贝构造+拷贝构造->构造	

	Date d;
	d =func3();//构造+构造+拷贝构造+赋值运算符重载->构造+构造+赋值运算符重载

	return 0;
}

大家有兴趣的可以下去试一下,就用我上面的代码,但是要注意并不是所有的编译器都支持或者都会优化的一样,以上是vs2022
对象返回总结:
①接收返回值对象,尽量拷贝构造方式接收,不要赋值接收
②函数中返回对象时,尽量返回匿名对象(匿名对象具有常属性)
函数传参总结:
①尽量使用const &传参

类和对象(下)(二)的知识大概就讲到这里啦,博主后续会继续更新更多C++的相关知识,干货满满,如果觉得博主写的还不错的话,希望各位小伙伴不要吝啬手中的三连哦!你们的支持是博主坚持创作的动力!

你可能感兴趣的:(C++的学习,c++,算法,开发语言)