【C++】——匿名对象+友元+内部类
匿名对象
接下来我们再来学一个知识叫做匿名对象,什么是匿名对象呢?
<font color = black>那现在呢有这样一个类: 我们现在想要那这个类去创建对象,那除了我们之前学的方法之外,其实我们还可以这样创建对象: 🆗,这里我们就拿A这个类创建了一个匿名对象。 匿名对象的特点就是没有名字,但是它的生命周期只在创建它的这一行。 我们可以来证明一下: 我们通过调式可以发现,113行执行完,这个匿名对象就已经调用了它的析构函数,即它的声明周期已经结束了。 但是要注意,和临时变量一样,如果我们用匿名对象去初始化一个引用的话,它的生命周期就会被延长至该引用被销毁。并且这里肯定都要加const的,因为临时变量和匿名对象都具有常性。
那匿名对象有什么用呢?
<font color = black>既然创造出来,就一定是有用的。 比如: 现在有一个类
Solution
,里面有一个非静态成员函数Sum_Solution
,我们知道想要调用类里面的非静态成员函数,是需要通过对象去调用的。 那现在有了匿名对象,我们就可以这样调用了: 匿名对象在这样场景下就很好用,当然还有一些其他使用场景,这个我们以后遇到了再说。
4. 友元
友元分为:友元函数和友元类。
4.1 友元函数
那友元函数我们在上一篇文章是不是就用到了:
在上一篇文章我们实现的日期类中: 我们尝试去重载operator<,然后发现没办法将operator<<重载成成员函数。因为cout的输出流对象和隐含的this指针在抢占第一个参数的位置。this指针默认是第一个参数也就是左操作数了。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/42cc956881dd4d35a5736c43d00a48af.png) 但是实际使用中cout需要是第一个形参对象,才能正常使用。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/8d33e20789df481ea0bd92f61a997312.png) 所以要将operator<<重载成全局函数。但又会导致类外没办法访问成员,然后我们就使用友元解决了。operator>同理。 友元函数使得定义在类外部的普通函数可以直接访问类的私有和受保护成员,该函数不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
说明:
<font color = red>友元函数可访问类的私有和保护成员,但不是类的成员函数
友元函数不能用const修饰 经过之前的学习我们知道const修饰的是啥? const修饰非静态成员函数,实际修饰的是this指针,而友元函数根本都不是类成员函数,所以都没有this指针。
<font color = red>友元函数可以在类里面的任何地方声明,不受类访问限定符限制
<font color = red>一个函数可以是多个类的友元函数
<font color = red>友元函数的调用与普通函数的调用原理相同
4.2 友元类
接下来我们再来学习一下友元类:
我们来看这样一个场景:
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;
};
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;
};
<font color = black>现在有两个类,在Date类中有一个成员变量是Time类的对象。 Time类中的成员变量都是私有的,那在Date类中我们想访问Time类成员的私有成员变量,是不行的。 那想解决这个问题,除了去写Get和Set方法,还可以这样解决: 就是声明日期类为时间类的友元类,这样在日期类中就可以直接访问Time类成员中的私有成员变量了。
然后呢,友元类还有一些需要我们注意的地方:
友元关系是单向的,不具有交换性
比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
友元关系不能传递
若C是B的友元, B是A的友元,但不能说明C是A的友元。
<font color = red>友元关系不能继承,这个在后面讲到继承的时候再给大家详细介绍
5. 内部类
我们再来看一个东西叫做内部类,什么是内部类呢?
如果一个类定义在另一个类的内部,那么这个类就叫做内部类。
比如像这样:
class A
{
private:
int h;
public:
class B
{
private:
int b;
};
};
那大家先来思考一个问题:类A的大小是多少?
<font color = black>对于类A来说,首先有一个整型成员变量h,然后还有一个成员是类B,B里面也有一个整型成员变量。 那两个整型变量,A的大小是不是8个字节啊? 我们来验证一下: 欸,结果是4,为什么呢,里面不是还有一个类B嘛。 我们通过调式可以发现: 拿A定义一个对象,它的里面只有一个成员变量h,并没有类B。
所以呢:
<font color = black>这里想告诉大家的是: 内部类并不属于外部类,它和对应的外部类是相互独立的,只是受外部类类域的限制。 对于上面那个类来说,我们想拿A中的内部类B去创建对象,这样是不行的: 因为B是在A这个类域里面的。 这样就可以了。
另外呢:
内部类也是受访问限定符的限制的。 <font color = black>刚才类B在A中是Public修饰的,所以我们指定类域之后就可以访问了,但如果B被private修饰呢? 就不行了。
然后还有就是:
内部类天生就是其对应的外部类的友元类。 <font color = black>那这样的话,在B中就可以直接访问A中的私有成员了。 注意内部类可以直接访问外部类中的static成员,不需要通过外部类的对象/类名。 但是我们说了,友元关系是单向的,所以: 外部类对内部类没有任何的访问权限。
- 点赞
- 收藏
- 关注作者
评论(0)