类和对象之友元
Posted 可乐不解渴
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类和对象之友元相关的知识,希望对你有一定的参考价值。
友元
友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字
friend
。友元不是成员函数,但是它可以访问类中的私有成员,不可以使用对象名去调用它。
友元函数
友元函数是在类定义中由关键字friend
修饰的非成员函数
。其格式如下:
friend 返沪类型 函数名(形参表)
{
//函数体
}
示例
class Person
{
friend istream& operator>>(istream& in, Person& p); //全局函数做友元
private:
int m_A;
int m_B;
};
istream& operator>>(istream &in,Person &p)
{
in>>p.m_A>>p.m_B;
return in;
}
友元类
如果一个类声明为另一个类的友元,则该类称为另一个类的友元类
。若A类为B类的友元类,则A类的所有成员函数都是B类的友元函数,都是可以访问B类的任何数据成员。
友元类的声明是在类名之前加上关键字friend
实现的。声明A类为B类的友元类的格式如下:
class B
{
friend class A;
};
这里要注意一个问题,就是当声明A类为B类的友元类时,A类必须已经存在,但是如果A类又将B类声明为自己的友元类,又会出现B类不存在的错误。这种情况,C++专门规定了前向引用声明
,用与解决这类问题。
例如下述情况:
class B; //前向引用声明
class A //A类的定义
{
public:
void funA(B b); //以B类对象b为形参的成员函数
};
class B //B类的定义
{
public:
void funB(A a); //以A类对象a为形参的成员函数
};
示例
下面我们就写一个计算某次火车的旅途时间的友元类为例,加深对友元的掌握。
#include<iostream>
class TrainTrip; //前向引用声明
class Clock
{
friend class TrainTrip; //TrainTrip声明为Clock的友元类
public:
void ShowTime(); //显示时间函数
void SetTime(int h=0, int m=0, int s=0); //带有缺省值的设置时间函数
Clock(int h = 0, int m = 0, int s = 0); //带有缺省值的构造函数
private:
int m_hour; //小时
int m_minute; //分钟
int m_second; //秒
};
void Clock::ShowTime()
{
std::cout << this->m_hour << " :" << this->m_minute << " :" << this->m_second << std::endl;
}
void Clock::SetTime(int h , int m, int s)
{
this->m_hour = h;
this->m_minute = m;
this->m_second = s;
}
Clock::Clock(int h, int m, int s)
{
this->m_hour = h;
this->m_minute = m;
this->m_second = s;
}
class TrainTrip
{
public:
TrainTrip(char* No, Clock S, Clock E); //构造函数
Clock TripTime();
private:
char* m_TrainNo; //车次
Clock m_StartTime; //出发时间
Clock m_EndTime; //到达时间
};
TrainTrip::TrainTrip(char* No, Clock S, Clock E)
{
this->m_TrainNo = No;
this->m_StartTime = S;
this->m_EndTime = E;
}
Clock TrainTrip::TripTime()
{
int tmpH;
int tmpM;
int tmpS;
int carry = 0;
Clock tmpTime;
if ((tmpS=this->m_EndTime.m_second - this->m_StartTime.m_second) > 0)
{
carry = 0;
}
else
{
tmpS += 60;
carry = 1;
}
if ((tmpM = this->m_EndTime.m_minute - this->m_StartTime.m_minute-carry) > 0)
{
carry = 0;
}
else
{
tmpM += 60;
carry = 1;
}
if ((tmpH = this->m_EndTime.m_hour - this->m_StartTime.m_hour - carry) > 0)
{
carry = 0;
}
else
{
tmpH += 24;
}
tmpTime.SetTime(tmpH, tmpM, tmpS);
return tmpTime;
}
int main()
{
Clock c1(8, 10, 10), c2(6, 1, 2);
Clock c3;
TrainTrip t1((char*)"G663",c1, c2);
c3 = t1.TripTime();
c3.ShowTime();
return 0;
}
结果如下图所示:
★总结
- 友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。
- 友元函数不能用const修饰。
- 友元函数可以在类定义的任何地方声明,不受类访问限定符限制
- 一个函数可以是多个类的友元函数。
- 友元函数的调用与普通函数的调用和原理相同。
- 友元关系是不能传递的,B类是A类的友元,C类是B类的友元,在C类和A类之同,如果没有声明,就没有任何友元关系,就不能进行数据共享。
- 友元关系是单向的,如果声明B类是A类的友元,B类的成员函数就可以访同A类的私有和保护数据,但A类的成员函数不能访问B类的私有和保护数据。
- 在使用友元时必须要慎重,要具体问题具体分析,要在提高效率和增加共享之间把我好一个
度
,要在共享时和封装之间进行恰当的平衡。
END...
以上是关于类和对象之友元的主要内容,如果未能解决你的问题,请参考以下文章