【C++】——匿名对象+友元+内部类

举报
YIN_尹 发表于 2023/08/21 18:52:55 2023/08/21
【摘要】 匿名对象接下来我们再来学一个知识叫做匿名对象,什么是匿名对象呢?<font color = black>那现在呢有这样一个类: 我们现在想要那这个类去创建对象,那除了我们之前学的方法之外,其实我们还可以这样创建对象: 🆗,这里我们就拿A这个类创建了一个匿名对象。 匿名对象的特点就是没有名字,但是它的生命周期只在创建它的这一行。 我们可以来证明一下: 我们通过调式可以发现,113行执行...

匿名对象

接下来我们再来学一个知识叫做匿名对象,什么是匿名对象呢?

<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关键字。

说明:

  1. <font color = red>友元函数可访问类的私有和保护成员,但不是类的成员函数

  2. 友元函数不能用const修饰 经过之前的学习我们知道const修饰的是啥? const修饰非静态成员函数,实际修饰的是this指针,而友元函数根本都不是类成员函数,所以都没有this指针。

  3. <font color = red>友元函数可以在类里面的任何地方声明,不受类访问限定符限制

  4. <font color = red>一个函数可以是多个类的友元函数

  5. <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类成员中的私有成员变量了。 在这里插入图片描述 在这里插入图片描述

然后呢,友元类还有一些需要我们注意的地方:

  1. 友元关系是单向的,不具有交换性

比如上述Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。

  1. 友元关系不能传递

若C是B的友元, B是A的友元,但不能说明C是A的友元。

  1. <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成员,不需要通过外部类的对象/类名。 但是我们说了,友元关系是单向的,所以: 外部类对内部类没有任何的访问权限。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。