当前位置:网站首页>友元类和友元函数
友元类和友元函数
2022-08-09 22:08:00 【北冥有鱼丶丶】
一.友元函数
问题:现在尝试去重载operator<<,然后发现没办法将operator<<重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。但是实际使用中cout需要是第一个形参对象,才能正常使用。所以要将operator<<重载成全局函数。但又会导致类外没办法访问成员,此时就需要友元来解决。operator>>同理。
class Date
{
public:
Date(int year, int month, int day)
: _year(year)
, _month(month)
, _day(day)
{}
ostream& operator<<(ostream& _cout)
{
_cout << _year << "-" << _month << "-" << _day << endl;
return _cout;
}
//这实际上是 d1 << cout; -> d1.operator<<(&d1, cout); 不符合常规调用
// 因为成员函数第一个参数一定是隐藏的this,所以d1必须放在<<的左侧
private:
int _year;
int _month;
int _day;
};
友元函数可以直接访问类的私有成员,但它不是类的成员函数,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字,它可以在类定义的任何地方声明,不受类访问限定符限制。
一个函数可以是多个类的友元函数,友元函数不能用const修饰,因为const指针修饰的是this所指向的对象,但是友元函数没有隐藏的this指针
class Date
{
friend ostream& operator<<(ostream& _cout, const Date& d);
friend istream& operator>>(istream& _cin, Date& d);
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
private:
int _year;
int _month;
int _day;
};
ostream& operator<<(ostream& _cout, const Date& d) {
_cout << d._year << "-" << d._month << "-" << d._day;
return _cout;
}
istream& operator>>(istream& _cin, Date& d) {
_cin >> d._year;
_cin >> d._month;
_cin >> d._day;
return _cin;
}
int main()
{
Date d;
cin >> d;
cout << d << endl;
return 0;
}
二.友元类
==友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
友元关系是单向的,不具有交换性。
比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time
类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
友元关系不能传递。
如果B是A的友元,C是B的友元,则不能说明C时A的友元。
友元关系不能继承。
class Time
{
friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问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;
};
class Date
{
public:
Date(int year = 1900, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _day(day)
{}
void SetTimeOfDate(int hour, int minute, int second)
{
// 直接访问时间类私有的成员变量
_t._hour = hour;
_t._minute = minute;
_t._second = second;
}
private:
int _year;
int _month;
int _day;
Time _t;
};
内部类:
如果一个类定义在另一个类的内部,那么这个类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。内部类可以定义在外部类的public、protected、private都是可以的。注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
sizeof(外部类)=外部类的大小,和内部类没有任何关系。同时算一个类的大小与其中的静态成员变量也没有任何关系,因为我们计算一个类的大小,本质上是计算该类所定义对象的大小,但是静态变量存并不是存储在类中,而是存储在静态区中的,所以对象大小不包括静态成员变量的大小,那么类的大小也就不包括静态成员变量的大小。
内部类实际上就是外部类的友元类(但是外部类不是内部类的友元),内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
内部类受访问限定符的限制。
class A {
private:
static int k;
int h;
public:
class B // B天生就是A的友元
{
public:
void foo(const A& a)
{
cout << k << endl;//OK
cout << a.h << endl;//OK
}
};
};
int A::k = 1;
int main()
{
A::B b;
b.foo(A());
return 0;
}
边栏推荐
猜你喜欢
随机推荐
【Apifox】为什么如此受青睐,此篇文章和大家分享
leetcode:323. 无向图中连通分量的数目
leetcode:321. 拼接最大数
Leetcode 98. 验证二叉搜索树
p5.js实现的炫酷星体旋转动画
18-GuliMall 压力测试与性能监控
The 2022-8-9 sixth group of input and output streams
少儿编程 电子学会图形化编程等级考试Scratch三级真题解析(判断题)2022年6月
PyQt5:入门使用教程
APS系统能消除造成生产和运输延迟的瓶颈
Postgresql源码(68)virtualxid锁的原理和应用场景
B. Applejack and Storages
【微信小程序开发(八)】音频背景音乐播放问题汇总
【对象——对象及原型链上的属性——对象的操作方法】
Chapter 15 HMM模型
Qt message mechanism and events
毕昇编译器优化:Lazy Code Motion
Tencent continues to wield the "big knife" to reduce costs and increase efficiency, and free catering benefits for outsourced employees have been cut
MySQL——JDBC
Analyses the development status quo of stock trading