zoukankan      html  css  js  c++  java
  • 友元

    【1】友元常识点

    (1)理论知识

    <1> 友元分为友元类和友元函数,而友元函数又分为普通函数和成员函数。

    <2> 友元具有三个性质:

    [1] 不具有对称性:A是B的友元,不能说明B就是A的友元

    [2] 不具有传递性:A是B的友元,B是C的友元,不可以认为A是C的友元

    [3] 不具有继承性:继承关系中不存在友元的传递

    (2)示例代码

    <1> 友元类

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Base;
     5 
     6 class Test
     7 {
     8     friend class Base; // 友元类
     9 
    10 public:
    11     void display()
    12     {
    13         cout << "a = " << m_a << endl;
    14         cout << "b = " << m_b << endl;
    15     }
    16 
    17     void setBaseObj(Base* pBase)
    18     {
    19         m_pBaseObj = pBase;
    20 //      m_pBaseObj->m_ca = 100;  // Error:使用未定义类型Base 即使m_ca是公有成员变量
    21 //      auto tempObj = m_pBaseObj->m_ea;  //Error:使用未定义类型Base 成员Base::m_ea不可访问,因为m_ea是私有成员变量
    22     }
    23 
    24 private:
    25     Test(int x = 0, int y = 0, Base* p = nullptr) : m_a(x), m_b(y), m_pBaseObj(p)
    26     {}
    27 
    28 private:
    29     int m_a;
    30     int m_b;
    31 
    32     Base* m_pBaseObj;
    33 };
    34 
    35 class Base
    36 {
    37 public:
    38     void display()
    39     {
    40         m_objt.display();
    41         m_objt.m_a = 10;
    42         m_objt.m_b = 20;
    43         m_objt.display();
    44     }
    45 
    46 public:
    47     int m_ca;
    48 
    49 private:
    50     Test m_objt;
    51     int m_ea;
    52 };
    53 
    54 int main()
    55 {
    56 //  Test objt; // Error:无法访问 private 成员(在“Test”类中声明) 构造函数私有访问限制
    57     
    58     Base b1;
    59     b1.display();
    60 
    61     return 0;
    62 }
    63 
    64 /*
    65 a = 0
    66 b = 0
    67 a = 10
    68 b = 20
    69 */

     简单说明:

    第8行:Base是Test的友元类,意味着Base类中可以访问Test类的私有成员,即41、42行的代码正常的理论基础。

    友元不具有对称性,即Test类中无法访问Base类的私有成员。原因分析:

    其实,根据实际逻辑理解,类的定义必定有先后之分。此示例中,Test类先于Base类进行定义。

    尤其注意,即使Base类前置声明,但Test类中也仅可以声明Base类的指针、引用等,不能定义Base类型的对象。

    可以想象一下,仅仅第4行执行过后,编译器只知道会有这样一个类型Base,但是这个类型到底内部长啥样子编译器还一概不知。

    基于这种定义的先后顺序限制,必然导致Test类中无法通过Base类指针(m_pBaseObj)或引用访问其成员变量(第20、21行,注释Error的原因所在)。

    <2> 普通函数作为友元函数

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Test
     5 {
     6 public:
     7     Test(int x = 0) : m_a(x)
     8     {}
     9 
    10     void print();
    11 
    12     // 普通函数作为类Test的友元函数
    13     friend void fun(Test & t);
    14 
    15 private:
    16     int m_a;
    17 };
    18 
    19 void Test::print()
    20 {
    21     cout << "this->m_a: " << m_a << endl;
    22 }
    23 
    24 void fun(Test& t)
    25 {
    26     t.m_a = 100;    // 访问对象的私有成员变量m_a
    27 }
    28 
    29 int main()
    30 {
    31     Test tt;
    32     fun(tt);
    33     tt.print();  // this->m_a: 100
    34 
    35     return 0;
    36 }
    37 
    38 /*
    39 this->m_a: 100
    40 */

    第13行:fun函数作为Test类的普通(与成员函数区分)函数,参数为Test类型对象的引用。

    普通与成员函数从代码上如何区分?第24行,fun函数的定义时,没有加类的作用域(比如第19行的写法),视为普通函数。

    第26行:fun函数定义时,如果内部想访问参数t的私有成员变量,理论上是禁止的。

    解决方案:把fun函数定义为Test类的友元函数,即声明时加上friend关键字即可。

    <3> 成员函数作为友元函数

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Test
     5 {
     6     int m_a;
     7 
     8 public:
     9     Test(int x = 0) : m_a(x)
    10     {}
    11 
    12     void print();
    13 
    14     friend class Base; // 友元类
    15 };
    16 
    17 void Test::print()
    18 {
    19     cout << "this->m_a: " << m_a << endl;
    20 }
    21 
    22 class Base
    23 {
    24 public:
    25     int m_b;
    26     Base(int y = 0) : m_b(y)
    27     {}
    28 
    29     void fun(Test& t);  // Base类的成员函数 作为 Test类的友元函数
    30 };
    31 
    32 void Base::fun(Test& t)
    33 {
    34     t.m_a = 200;   // 访问对象的私有成员变量m_a
    35 }
    36 
    37 int main()
    38 {
    39     Test t1;
    40     Base b1;
    41     b1.fun(t1);
    42     t1.print();  // this->m_a: 200
    43 
    44     return 0;
    45 }
    46 
    47 /*
    48 this->m_a: 200
    49 */

    成员函数欲作为友元函数,必须先建立友元类关系基础。

    因为成员函数作为友元函数,是基于友元类前提下的“肆无忌惮”。

    如上示例:第14行,Base类是Test类的友元类,意味着Base类中可以随便访问Test类的所有成员变量。

    因此,私认为Base类的fun成员函数是Test类的友元函数,尽管没有直接加friend关键字,但作用与友元函数相当。

    第34行,可以随便访问私有成员变量m_a

    [3] 理解友元

    好基友,一辈子,关系好了要啥都随便哈。

    Good Good Study, Day Day Up.

    顺序 选择 循环 总结

    作者:kaizen
    声明:本文版权归作者和博客园共有,欢迎转载。但未经作者同意必须保留此声明,且在文章明显位置给出本文链接,否则保留追究法律责任的权利。
    签名:顺序 选择 循环
  • 相关阅读:
    Day10 python基础---函数进阶
    Day9 python基础---函数初识
    Day8 python基础
    Day7 python基础
    Day6 python基础
    Day5 python基础
    Day4 python基础
    Day3 python基础
    TensorFlow学习笔记5-概率与信息论
    TensorFlow学习笔记6-数值计算基础
  • 原文地址:https://www.cnblogs.com/Braveliu/p/2844232.html
Copyright © 2011-2022 走看看