c++----类与对象(下)

      当我们简单的学习了上一篇日期类。简单的理解并且使用了我们前面学习的知识。当然这还只是我们c++的九牛一毛。并且我们的类与对象的知识还没学习完。今天我们来把类与对象的知识完善一下。

初始化列表

        那么今天我们就不讲废话了,我们直接来主题。首先我们可以看到我们这个题目。初始化列表,首先我们可以从题目中看出我们还是初始化。但是又不是我们以前的一个一个说话,而是一群说实话,毕竟列表嘛肯定都是多个才算得上是列表。然后呢依照我们的惯性,大家知道类与对象大多数知识点都是有很多的,我们这个初始化列表呢也有很多。但是能到家看我前面两篇博客之后,再来理解初始化列表的话就会容易很多了。首先我们来看一下这些有多少点吧。

之前我们实现构造函数时,初始化成员变量主要使⽤函数体内赋值,构造函数初始化还有⼀种⽅
式,就是初始化列表,初始化列表的使⽤⽅式是以⼀个冒号开始,接着是⼀个以逗号分隔的数据成
员列表,每个"成员变量"后⾯跟⼀个放在括号中的初始值或表达式。
每个成员变量在初始化列表中只能出现⼀次,语法理解上初始化列表可以认为是每个成员变量定义初始化的地⽅。
引⽤成员变量,const成员变量,没有默认构造的类类型变量,必须放在初始化列表位置进⾏初始
化,否则会编译报错。
C++11⽀持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显⽰在初始化列表初始化的成员使⽤的。
尽量使⽤初始化列表初始化,因为那些你不在初始化列表初始化的成员也会⾛初始化列表,如果这个成员在声明位置给了缺省值,初始化列表会⽤这个缺省值初始化。如果你没有给缺省值,对于没有显⽰在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。对于没有显⽰在初始化列表初始化的⾃定义类型成员会调⽤这个成员类型的默认构造函数,如果没有默认构造会编译错误。
初始化列表中按照成员变量在类中声明顺序进⾏初始化,跟成员在初始化列表出现的的先后顺序无关。建议声明顺序和初始化列表顺序保持⼀致。
       那么呢我们还是老样子,从第一点开始,首先呢第一点就是告诉我们初始化列表的剧本格式。大体可以看到首先是一个冒号,然后就是我们的成员变量后面跟个括号,然后一个逗号就跟着另外一个如此反复。

       大家可以看看这个图片。那还是很简单的,首先我们创建一个类,将类的访问限定符设定好之后我们再创建。因为我们初始化列表相当于构造函数嘛,还是利用构造函数的规则,首先我们需要将它的名与类相同。然后就是我们的参数。现在的区别就是我们可以连续的构造函数我们只需要在第二行中打出一个冒号,之后就是我们的参数初始化。但是在每一个参数中,后面都要写个括号,然后写给定的值。可以是自己写,也可以是利用我们传的参数来定义。每一个参数只需要在括号后面用逗号隔开就可以了,最后不需要用结尾来收尾,因为我们会在下面用一个花括号结尾。当然也可以将各个参数列在一行,但那样会不够美观,也不够容易分辨,所以我们普遍是一个参数定义一行。

       那么第一点就很好理解了,然后这是我们的第2点。第2点的代表的意思就是说我们初始化列表中每一个成员只能初始化一次。这就好比我们的限量一份的物品,你已经拿了一次,然后你不能说你再排一次队,然后就再拿一次,这肯定是没办法的,然后这里会主动给你们报出错误。

        对于第3点就是说初始化列表对这三个来说必须使用。没有的话就是错误的。

        然后大家看到第4点缺省值是不是很熟悉呀?并且还是在成员变量声明的位置给缺省值,这就说有点儿像我们当时最开始定义的时候给他一个值。然后他后面交代这个字的作用就是当我们没有显示初始化列表的时候,他给我们定义的时候的值给他。就有点像我们以前学c的时候的最开始的初始化定义。

        我们大家看看第5点,它上面写的是尽量使用初始化列表初始化,但其实大家都知道这样说的话多半就是叫我们以后使用初始化列表来初始化。然后他们给出的理由说是我们初始化成员无论如何都会走一遍初始化列表。对于我们给了缺省值初始化的时候,初始化列表如果也没有给成员声明的话,那么就会用我们的确省值来初始化。如果我们的缺省值都没有的话,那么就会取决于编译器来一个随机值。所以这就是告诉我们,当我们大家不够仔细的时候,可以在定义的时候给他的确认值,这样方便我们后面使用,也不至于报错。

        大家看看我上面的这个图片,首先呢我这里虽然用了初始化列表,但是我并没有将它完全初始化,我只将year给初始化了,但是关于月份和天数我都没有初始化,所以因为我们没有初始化,所以它就会调用我们的定义缺省值。大家也可以看到我们的最后的结果,关于年份打印来的是二,最后的月份是一,然后日期是随机值,因为我们并没有给缺省值,由编译器确定,那么它就是随机值了。所以这就印证了我们的第5点,当我们没有用初始化的时候,它就会用我们的初始化列表来初始化。 

       然后第6点就很老套了,我们在前面说过他的调用顺序。就只是告诉我们初始列表的调用顺序还是跟构造的一样定义先调用这个大家知道就可以了。

类型转换

        好了,上面就是我们初始化列表的知识了,接下来我们要讲的是我们前面说过的c++的类型转换,最开始说嘛,我们c++打印不需要写出数据类型的嘛。我们当时不是提及过c++会自动转换数据类型的嘛。今天我们这里就在说明一下。我们就先简单的举一个例子大家来看看我们的类型转换:

        虽然我们这里举个例子不是很好,但是大家还是能够直观的看到原本我们给i的值为1,但是最后我们将它转化为了char类型的,然后我们将打印出来,可以看到我们并没有报错,而是打印出来的一个方括号,这就也是相当于我们打印出来了,只是因为我们存放的是1与char的类型不同,所以它就直接打印出来,所以结果不同。但是这也完全的展示出来我们的类型转换。

        构造函数前⾯加explicit就不再⽀持隐式类型转换,然后我们都知道有些时候也并不是全部转换都好,所以呢如果当我们不想再用类型转换的时候只需要在前面加一个explicit就可以了。当然我们现在讲的类型转换是明示的,因为这是我们人为写的让他内心转换的,所以这就叫明示。然后我们其实普遍使用的都是隐式,就是说我们只管他用就行了,并不将他明确的表示出来。

        当我们加入了这个关键词之后,我们后面的构造函数就不会再支持类型转换了。当然其实很多情况我们是不写这个关键词的,因为有时候还能给自己心理安慰吧。 当然这时候有人就会想,反正有影视类型转换吧,对于我们有什么作用呢?我们学这个有什么用呢?其实对于这个影视类型转换创建的初衷是为了给我们方便,至于如何方便呢?大家看下面这张图片:

         不知道大家有没有看懂上面的这张图片,这张图片我们先看我们的主函数中,我们主函数中调用了两次print1因为我们给他为了区分,所以给它们的值不一样,首先我们可以看到我们第一次给他的值为0,所以他们打印出来的零,但是我们第二次调用的时候,我们只给写了个三,然后他就打印出三了,大家看出区别了吗?大家可以看到我们第一次调用写了三行啊。是吧。但是我们第二次调用只写了一行,这就是我们隐式类型转换的好处,可以大大节约我们的时间成本。且第二次写的那个更加方便,是吧?我相信大家都会使用这个。所以这就是那影视类型转换被创建出来的原因,方便我们使用。

       当然c++也是支持多参数转化的单只有在C++11之后才⽀持多参数转化

static成员

        好了,上面就是我们类型转化的知识了,接下来我们是要学习一个关键词它是用来修饰成员变量的,但凡是被修饰的成员变量被称之为静态成员变量。就是我们标题。这个大家一看就知道,还是比较麻烦的。毕竟修饰嘛居然需要我们自己写,那么肯定有很多条条框框的,所以让我们先来看一下他的几点规则。

static修饰的成员变量,称之为静态成员变量,静态成员变量⼀定要在类外进⾏初始化。
静态成员变量为所有类对象所共享,不属于某个具体的对象,不存在对象中,存放在静态区。
⽤static修饰的成员函数,称之为静态成员函数,静态成员函数没有this指针。
静态成员函数中可以访问其他的静态成员,但是不能访问⾮静态的,因为没有this指针。
⾮静态的成员函数,可以访问任意的静态成员变量和静态成员函数。
突破类域就可以访问静态成员,可以通过类名::静态成员 或者 对象.静态成员 来访问静态成员变量 和静态成员函数。
静态成员也是类的成员,受public、protected、private 访问限定符的限制。
静态成员变量不能在声明位置给缺省值初始化,因为缺省值是个构造函数初始化列表的,静态成员变量不属于某个对象,不⾛构造函数初始化列表。
       大家看到了吧?这个修饰词也是有不少的条条框框的,那么我们还是从第一点开始讲解起。首先他第一点告诉我们static修饰的成员变量被称为成员变量,然后成员变量是在外面初始化的,这就说明什么?我们是在类里面定义在内外面初始化。具体是以下这个样子。

         我们可以看到我们的_scount声明与初始化是分开的并且我们在声明的时候写了static的。

        然后我们第二点讲的就是被static修饰的变量都会可以被类对象所引用,并且不属于的类的某一个地方。它是存放在静态区的,这个大家在c的时候学习过吧,我们在静态区是存放静态变量的。第二点就是告诉我们他存放在静态区的

       第3点是告诉我们静态成员变量的一个特点。都没有this指针。这就表示我们如果需要在外面引用的话,就必须要特定的指示才行。当然我们在类里面是可以随便使用的。在外面就要特定的指示,接下来会讲到。

       第4点和第5点我们就结合讲,第4点讲的就是我们在那里面可以直接访问。没有被static修饰的成员函数就可以直接访问静态成员函数。其实这就有点独权了,因为我们感觉这个只是对内部人员好,如果外部人员需要使用的话就必须用一定的格式才能引用成静态成员变量。接下来就先直接尝试给大家看一下类域函数的人访问静态成员。

        我们可以看到我们在主函数中调用这个static的时候是姓名加两个冒号加成员。这样才被调用的,这就是我们静态成员在内域外被调用时的格式。

       然后对于第6点来说,就是说我们现在静态成员也是那里面的访问限定符限制。这个没有什么太多的解释。

       第七点,也就是我们最后一点就是在告诉我们不要在声明到时候给他缺省值。是因为静态成员变量它不属于任何一个对象,它存在静态区,它不会走构造函数。所以我们不要给他缺省值得要在最后外面定义的时候给他确定的值。

        对于static来说,我们大概只需要知道这两点,首先它是存放在静态区的,不属于任何一个具体的对象,并且他没有this指针,其他的大概大家都看看两遍就可以了。

 友元

       Ok,接下来我们讲一个很有意思的访问限定的声明。我说他很有意思呢,因为这很像我们现在日常生活中的一些男女朋友关系。男生对女生一心一意,但是女生却对男生丝毫不在意。有的时候女方可以到男方家里,但是她并不会让男方到女方家里。当然这只是一个课外面的聊,只是声明一下吧,然后今天我们的这个叫友元。当然这里也祝愿大家对自己的心上人有缘。

       对于这种访问限定的肯定也是有很多点的,但其实这个其实是很简单的。那么我们接下来直接看一看。

友元提供了⼀种突破类访问限定符封装的⽅式,友元分为:友元函数和友元类,在函数声明或者类声明的前⾯加friend,并且把友元声明放到⼀个类的⾥⾯。
外部友元函数可访问类的私有和保护成员,友元函数仅仅是⼀种声明,他不是类的成员函数。
友元函数可以在类定义的任何地⽅声明,不受类访问限定符限制。
⼀个函数可以是多个类的友元函数。
友元类中的成员函数都可以是另⼀个类的友元函数,都可以访问另⼀个类中的私有和保护成员。
友元类的关系是单向的,不具有交换性,⽐如A类是B类的友元,但是B类不是A类的友元。
友元类关系不能传递,如果A是B的友元, B是C的友元,但是A不是B的友元。
有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多⽤。
       首先第一点就是在对我们说有缘可以是一个函数,也可以是一个类。对于声明一个函数的话,我们就在这个函数前面加一个friend,并且把它放在类里面就可以了。

         这里我们可以看到我们的c是在类B外面的。并且大家可以看到我们这个是编译器里面没有报错的。所以这就可以知道我们这个是可以使用的。

        对于第二点呢,他就是给我们说我们的外部友元函数,就只是可以访问而已,它并不是类里面的成员函数。并且可以访问你的任何修饰,意思就是说他并不会被类的访问限定符给限制住。

        然后对于第3点来说,友元函数可以在类的任何地方声明。是说我们可以在开头或者结尾或者中间那一个地方声明一下,写一下,想着写就可以了。这两点还是很好理解的。

       第四点就更好理解了,这就是说我们一个外部函数可以在多个类里面声明:

         然后第5点就是说我们第一点说的友元类。然后我们这个外部的类就可以访问这个类中的任何成员了。当然这就是一个我们刚刚写的有原函数一样,只是将函数换成了类而已。

       然后第6点和第7点,这就是我在最开始说的一个男女关系的这个解释。首先就是单向的,我男生可能是爱着女生的,但是女生不一定是爱着男生的。想要男生女生很爱着男生,就必须将女生也在男生那里表明就是说我需要将类a友元声明到类b。然后第7点呢这就是说女朋友的朋友就是闺蜜吧,可能不是我的朋友。只能说闺蜜可能是女朋友的好朋友,

         然后第8点就是告诉我们,虽然友元很好用,但是不能多用,因为它有时候可能会让我们的函数封装函数给破坏掉。大家还是尽量少用吧,不要多用。毕竟大家都知道朋友太多也不是什么好事,指不定哪个朋友就害了我们。

       所以友元函数就是这样子的。那这也可以将它理解为一个朋友。因为我是你的朋友,所以我可以到你家里玩,用你家里的东西。我可以是你的朋友,你也可以是我的朋友,但是如果我不认可你的话,你就不能到我家里玩,就你就不能用我的东西。然后就是你家里的规矩对我这个客人来说可能是不管用的,也就是说有原函数声明在内,不受访问限定符的限制。然后朋友的朋友不一定是我的朋友。所以我觉得友元声明挺像现在社会的。

内部类

        我们马上来讲的另外一个知识点叫内部类。是对于这个知识点来说,有一点像我们刚刚讲的友元类。所谓内部类就是将一个类定义在另一个类的内部内部类是⼀个独⽴的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。 我们普遍把内部类默认是外部类的友元类。

       内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使⽤,那么可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地⽅都⽤不了。

       当我们理解了友元声明后,我们来看内部类就很好理解。可以理解为友元类。 但是会被访问限定符限制      

匿名对象

        不知道大家看见这个标题会想到什么?匿名对象感觉很神秘的样子啊。其实说神秘吧,不是很神秘,用类型(实参) 定义出来的对象叫做匿名对象,相⽐之前我们定义的类型象名(实参) 定义出来的叫有名对象。但是匿名对象⽣命周期只在当前一行,⼀般临时定义⼀个对象当前用⼀下即可,就可以定义匿名对象。

       对于匿名对象反正对于我来说现在还是很少使用的。当然大家还是可以下去练习使用的。

总结

        好了,上面就是类与对象下的全部知识点的这篇博客结束之后,我们的c++入门类与对象就完全结束了。但是大家千万不要松懈,因为我们类与对象几乎就是我们c++入门的基础。后面会很多次使用类与对象中的知识点,所以大家后面还是需要多看看,多尝试背一下。记在自己的脑海中,当最后需要使用的时候就能想起来。然后大家需要本篇博客的练习代码的话,可以点击下面的代码:杨红和段/7月31号icon-default.png?t=N7T8https://gitee.com/yang-hong-and-duan/july-31st.git

  • 30
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值