C++ 类和对象(友元、内部类、匿名对像)

打印 上一主题 下一主题

主题 845|帖子 845|积分 2535

目录

一、媒介
二、正文
1.友元
1.1友元函数的使用
1.1.1外部友元函数可访问类的私有成员,友员函数仅仅是一种声明,他不是类的成员函数。
1.1.2一个函数可以是多个类的友元函数
2.友元类的使用
2.1什么是友元类
2.2 友元类的关系是单向的,不具有交换性。
2.3 友元类关系不能传递。
3.内部类
3.1内部类的使用
3.1.1 由于内部类是一个独立的类,跟定义在全局相比,它只是受外部类类域限制和访问限定符限制,以是外部定义的对象不包含内部类。
3.1.2内部类默认是外部类的友元类
4.匿名对象
4.1匿名对象的应用场景


一、媒介

   昨天我们已经分享了类和对象中范例转换和static成员的知识,有爱好的小同伴可以看一下:
  https://blog.csdn.net/yiqingaa/article/details/144066165
  本日让我们在一起学习类和对象中的友元、内部类,和匿名对象吧。
  二、正文

1.友元

   

  • 友元提供了一种突破类访问限定符封装的方式,友元分为:友元函数和友元类,在函数声明或者类声明的前面加friend,并且把友元声明放到一个类的里面。
  • 外部友元函数可访问类的私有和掩护成员,友元函数仅仅是一种声明,他不是类的成员函数。
  • 友元函数可以在类定义的任何地方声明,不受类访问限定符限制。
  • 一个函数可以是多个类的友元函数。
  • 友元类中的成员函数都可以是另一个类的友元函数,都可以访问另一个类中的私有和掩护成员。
  • 友元类的关系是单向的,不具有交换性,好比A类是B类的友元,但是B类不是A类的友元。
  • 友元类关系不能传递,如果A是B的友元,B是C的友元,但是A不是C的友元。
  • 有时提供了便利。但是友元会增加耦合度,粉碎了封装,以是友元不宜多用。 
  1.1友元函数的使用

   
 从上图可以看出在我们的Print函数中系统爆出了警告,说A::_a1、A::_a2是不可访问的。那是因为_a1、_a2被限定符private给限制住了,在类表面无法访问类里面的私有成员(这里是_a1和_a2)那么我们如何在类表面定义的函数访问我们的私有成员呢?这里我们就可以借助我们的友元函数来办理这个问题:
  1. #include<iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6.         friend void Print(const A& aa);//我们只需要把函数抄写一下放在类里面,然后前面加个friend就行。
  7.         A(int a1 = 1, int a2 = 2)
  8.         {
  9.                 _a1 = a1;
  10.                 _a2 = a2;
  11.         }
  12. private:
  13.         int _a1;
  14.         int _a2;
  15. };
  16. void Print(const A& aa)
  17. {
  18.         cout << aa._a1 << " " << aa._a2 << endl;
  19. }
  20. int main()
  21. {
  22.         A a;
  23.         Print(a);
  24.         return 0;
  25. }
复制代码

  友元函数的使用方法很简朴,只必要把定义在类表面的函数抄写一份到类里面,然后在函数前面加个friend就行了,friend+函数->友元函数(条件是这个函数定义在类表面,不然这么做其实无实际意义,毕竟如果这个函数是定义在类里面的,直接就可以调用私有成员。没必要多此一举)
  

  • 友员函数可以这么理解:之前我们是生疏人,我去你家里玩,私闯民宅这是违法的。不过现在我们是朋友了(我是你的友元函数,如上图中Print是类A的友元函数,即Print是A的朋友)那么我去你家玩,就没有任何问题了。
  • 友元可以定义在类里面的任何地方,哪怕是定义在限制符private里面都没问题,不过个人建议放在类里面的第一行,易于让人知道:哦,你使用了友元函数(清晰明白)。
  
  

  • 1.1.1外部友元函数可访问类的私有成员,友员函数仅仅是一种声明,他不是类的成员函数。
  

  如图所示,当我们想要通过  类名+::的方式去访问类中的公共成员的时间,只发现了类A的构造函数,而没有发现Print,这说明白友员函数仅仅只是一种声明,而非是这个类的成员函数。
  
  

  • 1.1.2一个函数可以是多个类的友元函数
  1. #include<iostream>
  2. using namespace std;
  3. class B;
  4. class A
  5. {
  6. public:
  7.         friend void Print(const A& aa,const B& bb);//Print是A的盆友
  8.         A(int a1 = 1, int a2 = 2)
  9.         {
  10.                 _a1 = a1;
  11.                 _a2 = a2;
  12.         }
  13. private:
  14.         int _a1;
  15.         int _a2;
  16. };
  17. class B
  18. {
  19. public:
  20.         friend void Print(const A& aa, const B& bb);//Print是B的盆友
  21.         B(int b1 = 3, int b2 = 4)
  22.         {
  23.                 _b1 = b1;
  24.                 _b2 = b2;
  25.         }
  26. private:
  27.         int _b1;
  28.         int _b2;
  29. };
  30. void Print(const A& aa,const B& bb)
  31. {
  32.         cout << aa._a1 << " " << aa._a2 << endl;
  33.         cout << bb._b1 << " " << bb._b2 << endl;
  34. }
  35. int main()
  36. {
  37.         A a;
  38.         B b;
  39.         Print(a,b);
  40.         return 0;
  41. }
复制代码

  由上图可知,函数Print不但是类A的盆友,同时也是类B的盆友。就像一个人可以是很多人的盆友一样,并不是独属于你的盆友。
  2.友元类的使用

   

  • 2.1什么是友元类
  定义:一个类可以将另一个类声明为它的友元类,被声明为友元的类将获得对原始类所有成员的访问权限,无论是私有、掩护照旧公有成员  。
  1. #include<iostream>
  2. using namespace std;
  3. class B;
  4. class A
  5. {
  6. public:
  7.         friend class B;//这里我们直接让B整个类都是A的盆友,这样我们不仅在Fun1函数中能使用A中隐私变量,在Func2中也能使用A中隐私成员。
  8.         A(int a1 = 1, int a2 = 2)
  9.         {
  10.                 _a1 = a1;
  11.                 _a2 = a2;
  12.         }
  13.         void Func1()
  14.                         {
  15.                                 cout<< _a1 << " " << _a2 << endl;
  16.                         }
  17. private:
  18.         int _a1;
  19.         int _a2;
  20. };
  21. class B
  22. {
  23. public:
  24.         B(int b1 = 3, int b2 = 4)
  25.         {
  26.                 _b1 = b1;
  27.                 _b2 = b2;
  28.         }
  29.         void Func2(const A& aa)
  30.         {
  31.                 cout << aa._a1 << " " << aa._a2 << endl;
  32.         }
  33.         void Func3(const A& aa)
  34.         {
  35.                 cout << aa._a1 << " " << aa._a2 << endl;
  36.         }
  37. private:
  38.         int _b1;
  39.         int _b2;
  40. };
  41. int main()
  42. {
  43.         A a;
  44.         B b;
  45.         b.Func2(a);
  46.         b.Func3(a);
  47.         return 0;
  48. }
复制代码
就比方上图所示,如果我们想在B类中任意使用A中的私有成员(_a1和_a2)我们可以让B一整个类都成为类A的友元,如许我们不但让类B中的Func1能访问到A中的私有成员(_a1和_a2),Func2中也能访问到A中的私有成员(_a1和_a2)。
  
  

  • 2.2 友元类的关系是单向的,不具有交换性。
  好比A类是B类的友元,但是B类不是A类的友元,我们如果想要在A类中访问B中私有成员(_b1和_b2)就访问不到。
  
  

  • 2.3 友元类关系不能传递。
  如果A是B的友元,B是C的友元,但是A不是C的友元。
  可以理解为我是你的盆友,你是他的盆友,但这并不意味着,我和他就是盆友。
  3.内部类

   

  • 如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,以是外部类定义的对象中不包含内部类。
  • 内部类默认是外部类的友元类。
  • 内部类本质也是一种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使用,那么可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地方都用不了。 
  3.1内部类的使用

   
  1. #include<iostream>
  2. using namespace std;
  3. class A
  4. {
  5. public:
  6.         A(int a1 = 1, int a2 = 2)
  7.         {
  8.                 _a1 = a1;
  9.                 _a2 = a2;
  10.         }
  11.         void Func1()const
  12.         {
  13.                 cout<< _a1 << " " << _a2 << endl;
  14.         }
  15.         class B
  16.         {
  17.         public:
  18.                 B(int b1 = 3, int b2 = 4)
  19.                 {
  20.                         _b1 = b1;
  21.                         _b2 = b2;
  22.                 }
  23.                 void Func2(const A&aa)
  24.                 {
  25.                         cout <<aa. _a1 << " " << aa._a2 << endl;
  26.                 }
  27.                         void Func3(const A& aa)
  28.         {
  29.                 cout << aa._a1 << " " << aa._a2 << endl;
  30.         }
  31.         private:
  32.                 int _b1;
  33.                 int _b2;
  34.         };
  35. private:
  36.         int _a1;
  37.         int _a2;
  38. };
  39. class B
  40. {
  41. public:
  42.         B(int b1 = 3, int b2 = 4)
  43.         {
  44.                 _b1 = b1;
  45.                 _b2 = b2;
  46.         }
  47. private:
  48.         int _b1;
  49.         int _b2;
  50. };
  51. int main()
  52. {
  53.         A a;
  54.         return 0;
  55. }
复制代码
上面就是我们简朴的写了个内部类。类B被定义在类A的内部。
  

  • 3.1.1 由于内部类是一个独立的类,跟定义在全局相比,它只是受外部类类域限制和访问限定符限制,以是外部定义的对象不包含内部类。
  

  看图可知,外部定义的对象a中没有类B,只有成员函数Fun1。
  
  

  • 3.1.2内部类默认是外部类的友元类
  

  因为B被定义在A中,以是B是A的盆友,即在B中可以任意访问到A中的私有成员。
  比方:B中的Func2和Func1都能访问到A的私有成员(_a1和_a2)。
  4.匿名对象

   

  • 用范例(实参)定义出来的对象叫做匿名对象,相比之前我们定义的 范例 对象名(实参) 定义出来的叫有名对象。
  • 匿名对象生命周期只在当前一行,一般临时定义一个对象当前用一下即可,就可以定义匿名对象。 
  

  如上图所示,就是有名对象和匿名对象的区别。
  值得注意的是:匿名对象的生命周期,只有该匿名对象创建的哪一行,一旦运行到下一行,该匿名对象就被销毁了。
  4.1匿名对象的应用场景

   匿名对象的使用主要是方便。比方:
  
我们只是想调用一下成员函数Func1:
  

  • 创造有名对象a,再通过实例化对象a访问Func1,必要两行代码。如上图标号1。
  • 直接创造匿名对象,直接访问Func1,只必要一行代码。如上图标号。
  现在知道匿名对象的作用了吗,其实就是为了图方便,能写一行代码完成的变乱,为什么要写两行呢,对吧。
  三结言
   本次博客的分享就到这呢,同学们咱们下次再见,拜拜喽。
  

  


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

一给

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表