zoukankan      html  css  js  c++  java
  • C++友元函数

      此文整理自C++_友元函数模板友元

      1. 引入友元函数原因

        在实现类之间数据共享时,减少系统开销,提高效率。

            具体来说:为了使其他类的成员函数直接访问该类的私有变量。

            即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。

            优点:能够提高效率,表达简单、清晰。

            缺点:友元函数破环了封装机制,尽量不使用友元函数,除非不得已的情况下才使用友元函数。

      2. 使用友元函数时机

            1)运算符重载的某些场合需要使用友元。

            2)两个类要共享数据的时候

      3. 如何使用友元函数

       3.1 友元函数的参数

         因为友元函数没有this指针,则参数要有三种情况:

            1)要访问非static成员时,需要对象做参数;--常用(友元函数常含有参数)

            2)要访问static成员或全局变量时,则不需要对象做参数

            3)如果做参数的对象是全局对象,则不需要对象做参数

       3.2 友元函数的位置

        因为友元函数是类外的函数,所以它的声明可以放在类的私有段或公有段且两者没有区别。

       3.3 友元函数的调用

        可以直接调用友元函数,不需要通过对象或指针。

       3.4 友元函数的分类

        根据这个函数的来源不同,可以分为三种方法:

      3.4.1 普通函数友元函数

            1)目的:使普通函数能够访问类的友元

            2)语法:

          声明位置:公有私有均可,常写为公有

          声明: friend + 普通函数声明

          实现位置:可以在类外或类中

          实现代码:与普通函数相同(不加不用friend和类::)

          调用:类似普通函数,直接调用

             3)示例代码:

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 class Example
     6 {
     7 public:
     8     Example(const int val = 0) : num(val){};
     9     virtual ~Example() {};
    10     friend void display(const Example& exam);
    11 
    12 private:
    13     int num;
    14 
    15 };
    16 
    17 void display(const Example& exam)
    18 {
    19     cout << exam.num << endl;
    20 }
    21 
    22 void main()
    23 {
    24     Example example(10);
    25     display(example);
    26 }
    View Code

      3.4.2 类Y的所有成员函数都为类X友元函数—友元类

            1)目的:使用单个声明使Y类的所有函数成为类X的友元

                它提供一种类之间合作的一种方式,使类Y的对象可以具有类X和类Y的功能

                 具体来说:

                    前提:A是B的友元(=》A中成员函数可以访问B中有所有成员,包括私有成员和公有成员)

                    则:在A中,借助类B,可以直接使用“B . 私有变量”的形式访问私有变量

            2)语法:

          声明位置:公有私有均可,常写为私有(把类看成一个变量)

                 声明: friend + 类名---不是对象啊

                 调用:

            3)示例代码:

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 class Boy;
     6 class Girl
     7 {
     8 public:
     9     Girl(){ name = "Lucy"; age = 18; };
    10     virtual ~Girl(){};
    11 
    12 private:
    13     char * name;
    14     int age;
    15     friend Boy;   //声明类Boy是类Girl的友元  
    16 
    17 };
    18 
    19 class Boy
    20 {
    21 public:
    22     Boy(){ name = "Jimmy"; age = 20; };
    23     virtual ~Boy(){};
    24     void display(Girl& girl);
    25 
    26 private:
    27     char * name;
    28     int age;
    29 
    30 };
    31 
    32 void Boy::display(Girl& girl) //函数disp()为类Boy的成员函数,也是类Girl的友元函数 
    33 {
    34     //正常情况,Boy的成员函数disp中直接访问Boy的私有变量
    35     cout << "Boy's name is: " << name << ", age: " << age << "." << endl;
    36 
    37     //借助友元,在Boy的成员函数disp中,借助Girl的对象,直接访问Girl的私有变量
    38     //而正常情况下,只允许在Girl的成员函数中访问Girl的私有变量
    39     cout << "Girl's name is: " << girl.name << ", age: " << girl.age << "." << endl;
    40 
    41 }
    42 
    43 
    44 int main()
    45 {
    46     Boy boy;
    47     Girl girl;
    48     boy.display(girl);  //b调用自己的成员函数,但是以girl为参数,友元机制体现在函数display中
    49 
    50     return 0;
    51 }
    View Code

      3.4.3 类Y的一个成员函数为类X的友元函数

            1)目的:使类Y的一个成员函数成为类X的友元

                 具体而言:而在类Y的这个成员函数中,借助参数X,可以直接以X。私有变量的形式访问私有变量

            2)语法:

          声明位置:声明在公有中 (本身为函数)

          声明:friend + 成员函数的声明

          调用:先定义Y的对象y---使用y调用自己的成员函数---自己的成员函数中使用了友元机制

            3)示例代码:

     1 #include <iostream>
     2 
     3 using namespace std;
     4 
     5 class Girl;
     6 class Boy
     7 {
     8 public:
     9     Boy(){ name = "Jimmy"; age = 20; };
    10     virtual ~Boy(){};
    11     void display(Girl& girl);
    12 
    13 private:
    14     char * name;
    15     int age;
    16 
    17 };
    18 
    19 class Girl
    20 {
    21 public:
    22     Girl(){ name = "Lucy"; age = 18; };
    23     virtual ~Girl(){};
    24 
    25 private:
    26     char * name;
    27     int age;
    28     friend void Boy::display(Girl& girl);   //声明类Boy的成员函数是类Girl的友元函数
    29 
    30 };
    31 
    32 //函数display()为类Boy的成员函数,也是类Girl的友元函数 
    33 void Boy::display(Girl& girl)
    34 {
    35     //正常情况,Boy的成员函数disp中直接访问Boy的私有变量
    36     cout << "Boy's name is: " << name << ", age: " << age << "." << endl;
    37 
    38     //借助友元,在Boy的成员函数disp中,借助Girl的对象,直接访问Girl的私有变量
    39     //而正常情况下,只允许在Girl的成员函数中访问Girl的私有变量
    40     cout << "Girl's name is: " << girl.name << ", age: " << girl.age << "." << endl;
    41 
    42 }
    43 
    44 int main()
    45 {
    46     Boy boy;
    47     Girl girl;
    48     boy.display(girl);  //b调用自己的成员函数,但是以girl为参数,友元机制体现在函数display中
    49 
    50     return 0;
    51 }
    View Code

      4. 模板友元函数

      在微软官方网站,有一个例子是用来说明如何建立模板友元的。下边是

       4.1 模板友元函数

      例子:

     1 #include <iostream>
     2 using namespace std;
     3 
     4 template <class T> class Array {
     5     T* array;
     6     int size;
     7 
     8 public:
     9     Array(int sz) : size(sz) {
    10         array = new T[size];
    11         memset(array, 0, size * sizeof(T));
    12     }
    13 
    14     Array(const Array& a) {
    15         size = a.size;
    16         array = new T[size];
    17         memcpy_s(array, a.array, sizeof(T));
    18     }
    19 
    20     T& operator[](int i) {
    21         return *(array + i);
    22     }
    23 
    24     int Length() { return size; }
    25 
    26     void print() {
    27         for (int i = 0; i < size; i++)
    28             cout << *(array + i) << " ";
    29 
    30         cout << endl;
    31     }
    32 
    33     template<class T>
    34     friend Array<T>* combine(Array<T>& a1, Array<T>& a2);
    35 };
    36 
    37 template<class T>
    38 Array<T>* combine(Array<T>& a1, Array<T>& a2) {
    39     Array<T>* a = new Array<T>(a1.size + a2.size);
    40     for (int i = 0; i < a1.size; i++)
    41         (*a)[i] = *(a1.array + i);
    42 
    43     for (int i = 0; i < a2.size; i++)
    44         (*a)[i + a1.size] = *(a2.array + i);
    45 
    46     return a;
    47 }
    48 
    49 int main() {
    50     Array<char> alpha1(26);
    51     for (int i = 0; i < alpha1.Length(); i++)
    52         alpha1[i] = 'A' + i;
    53 
    54     alpha1.print();
    55 
    56     Array<char> alpha2(26);
    57     for (int i = 0; i < alpha2.Length(); i++)
    58         alpha2[i] = 'a' + i;
    59 
    60     alpha2.print();
    61     Array<char>*alpha3 = combine(alpha1, alpha2);
    62     alpha3->print();
    63     delete alpha3;
    64 }
    template_friend 

      A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
      a b c d e f g h i j k l m n o p q r s t u v w x y z
      A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z  

      这个例子中,比较值得注意的是在类中声明模板友元函数部分:

    1 template<class T>
    2 friend Array<T>* combine(Array<T>& a1, Array<T>& a2);

      template<class T>这一句不可丢。友元函数的定义为:

    template<class T>
    Array<T>* combine(Array<T>& a1, Array<T>& a2) {
        Array<T>* a = new Array<T>(a1.size + a2.size);
        for (int i = 0; i < a1.size; i++)
            (*a)[i] = *(a1.array + i);
    
        for (int i = 0; i < a2.size; i++)
            (*a)[i + a1.size] = *(a2.array + i);
    
        return a;
    }

       4.2 模板友元类

      例子:

     1 // template_friend3.cpp
     2 // compile with: /EHsc
     3 #include <iostream>
     4 using namespace std;
     5 
     6 template <class T>
     7 class X
     8 {
     9 private:
    10     T* data;
    11     void InitData(int seed) { data = new T(seed); }
    12 public:
    13     void print() { cout << *data << endl; }
    14     template <class U> friend class Factory;
    15 };
    16 
    17 template <class U>
    18 class Factory
    19 {
    20 public:
    21     U* GetNewObject(int seed)
    22     {
    23         U* pu = new U;
    24         pu->InitData(seed);
    25         return pu;
    26     }
    27 };
    28 
    29 int main()
    30 {
    31     Factory< X<int> > XintFactory;
    32     X<int>* x1 = XintFactory.GetNewObject(65);
    33     X<int>* x2 = XintFactory.GetNewObject(97);
    34 
    35     Factory< X<char> > XcharFactory;
    36     X<char>* x3 = XcharFactory.GetNewObject(65);
    37     X<char>* x4 = XcharFactory.GetNewObject(97);
    38     x1->print();
    39     x2->print();
    40     x3->print();
    41     x4->print();
    42 }
    template_friend2

      65
      97
      A
      a

      5. 其他知识点

        1)友元函数和类的成员函数的区别:成员函数有this指针,而友元函数没有this指针。

        2)A是B的友元《=》A是B的朋友《=》借助B的对象,在A中可以直接通过“B.成员变量”(可以是公有,也可以为私有变量) 的方式访问B。

  • 相关阅读:
    go 注释/说明/文档 标注
    go stack object escape
    ubuntu virtualBox windows10 CPU占用100%
    git 团队合作
    git 修改远程pull和push地址
    go 项目编译失败
    fork函数 linux创建子进程
    51nod1183 编辑距离
    各种平衡树
    redis 配置多个ip 解决方案
  • 原文地址:https://www.cnblogs.com/xiehongfeng100/p/4044291.html
Copyright © 2011-2022 走看看