C++类和对象:友元

class Date
{ 
public:
	Date (int year,int _month, int _day)
		 :_year(year)
		 ,_month(month)
		 ,_day(day)
	{}
	void print()
	{
		cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	}
private:
 	int _year;
 	int _month;
 	int _day;
};
int main()
{
	Date d1(2021,7,15);
	d1.print();
	return 0;
}

对象可以通过上述方式进行打印,但是代码可读性低不直观;
对于内置类型的打印,我们之间用<<操作符输出;但是用<<操作符输出对象却会报错:

int a=10;
cout<<a<<endl;

Date d1(2021,7,15);
cout<<d1<<endl;//出错

所以要对<<操作符进行重载,操作符有两个操作数,一个是cout,一个是对象
cout是另外一个类创建出来的对象

改进

void operator<<(ostream& _cout)//_cout:是cout的别名,类型是输出流对象
{
	_cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
}
Date d1(2021,7,15);
d1.operator<<(cout);//所以将cout作为参数传递
//省略后d1<

被重载成类的成员函数,成员函数要用对象调用

  • d1.operator<<(cout);

被重载成类的成员函数,第一个参数是隐藏的this指针

  • <<操作符左边是对象,右边是参数;最后的调用方式是d1<与常使用的cout<<...相反

再改进:

class Date
{
	int getyear()const
	{
		return _year
	}
	int getmonth()const
	{
		return _month;
	}
	int getday()const
	{
		return _day
	}
};
ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout<<d.getyear()<<"-"<<d.getmonth()<<"-"<<d.getday()<<endl;
	return _cout;
}

有返回值的原因:

  • 如果没有返回值,不能连续输出对象cout<
  • cout是ostream类的对象;cout<这就是一个函数调用,该函数就有一个返回值,否则就不能连续输出

类中提供get函数的原因:

  • 要在类外访问私有的成员变量,如果不写那么就得将成员变量的权限设置为公有

再改进

通过友元

class Date
{
public:
	friend ostream& operator<<(ostream& _cout, const Date& d)
	//声明友元函数,也可以在类中实现
}
ostream& operator<<(ostream& _cout, const Date& d)
{
	_cout<<_year<<"-"<<_month<<"-"<<_day<<endl;
	return _cout;
}

在类中将运算符重载为类的友元函数(之前的重载函数都是将运算符重载为类的成员函数)
友元函数不属于类的成员函数,所以可以放在类中的任意位置声明

友元

类之间只允许通过公有的外部接口访问,不允许其它类程序代码访问自己的私有(或保护)成员。

  • 一个类的友元可以看做该类自已认可的朋友,允许该友元访问该类的私有或保护)成员。

也就是说,封装的两个类之间除了公有的接口外,没有其他的进入渠道,说类A是类B的友元,就像类B自己给类A开了一扇小窗,通过这扇窗,类A可以访问类B的私有信息

友元分友元类、友元成员函数和友元函数3种:

友元类:

class B
{
	friend class A;
}

在类B中声明类A是自己的友元,则称类A是类B的友元类,类A中所有成员函数都可访问类B的所有权限的成员(记忆时,类A在类B中定义,将A等同于B中的成员,A访问B的成员);

  • 友元关系是单向的,不具有交换性;类A是类B的友元类,但是类B不是类A的友元类
  • 友元关系不能传递;
    如果B是A的友元,C是B的友元,则不能说明C时A的友元。

友元成员函数:

class B
{
	friend void A::F();
}

类B中 定义类A的某个成员函数是自己的友元,则称该成员函数是类B的友元成员函数;
某成员函数是类B的友元成员函数,则该成员函数可以访问类B的所有成员

友元函数:

代码为:对<<操作符的重载
若类B定义某个函数是自己的友元,则称该函数是类B的友元函数。
某函数是类B的友元函数,则该函数可以访问类B的所有成员。

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

可以看出,友元为严密封装的类提供了方便快捷的访问途径,但友元也在某种程度上破坏了类的封装性。所以,程序中是否使用友元方法要权衡利弊,综合考虑。

内部类

一个类定义在另一个类的内部,这个内部类就叫做内部类

class B
{
	 class A
	 {
	 };
};

与友元类的相同点:

  • A可以访问B中的成员

不同点:

  • A是B中的成员,而在友元中,A只是在B中是声明;且用sizeof计算B大小,A不会影响B

内部类特性:

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名。
  3. sizeof(外部类)=外部类,和内部类没有任何关系。

你可能感兴趣的:(C++,c++)