C++友元 简述

#include "windows.h"
#include "iostream.h"


class FB;
class FA
{
public:
 FA()
 {
  strcpy(chMsg, "C++友元学习");
 };
 void Msg(FB & fb); //类的成员函数,其是类FB的友元函数
 friend void Msg2(FA & fa);
private:
 char chMsg[64];
};


void Msg2(FA & argu)
{
 cout<<argu.chMsg<<endl;
}


class FB
{
public:
 FB(char * Msg, char * Context)
 {
  strcpy(chMsg, Msg);
  strcpy(chContext, Context);
 };
 friend void FA::Msg(FB & fb);
private:
 char chContext[64];
 char chMsg[64];
};


void FA::Msg(FB & argu)
{
 TCHAR tchMsgWin[128] = {0};
 wsprintf(tchMsgWin, "FB:%s---FB:%s", argu.chMsg, argu.chContext);
 MessageBox(NULL, tchMsgWin, "C++友元", NULL);
 cout<<chMsg<<"::"<<argu.chMsg<<"|"<<argu.chContext<<endl;
}


void main()
{
 FB m_FB("窗口", "初始化");
 FA m_FA;
 m_FA.Msg(m_FB);

 Msg2(m_FA);

 cin.get();
}

 

 

友元函数说明如下:
1)必须在类的说明中说明友元函数,说明时以关键字friend开头,后跟友元函数的函数原型,友元函数的说明可以出现在类的任何地方,包括在private和public部分; 但要清晰一个概念:友元函数不属于类,只是可以通过参数传入类对象的引用,进而间接访问类的私有成员罢了;函数内不能出现类的this指针。
2)注意友元函数不是类的成员函数,所以友元函数的实现和普通函数一样,在实现时不用"::"指示属于哪个类,只有成员函数才使用"::"作用域符号,类的成员函数作为其它类的友元函数时,实现时还是要遵守类一般成员函数的规约;
3)友元函数不能直接访问类的成员,只能访问对象成员, 类似于约束5)
4)友元函数可以访问对象的保护、私有成员,但普通函数不行;
5)调用友元函数时,在实际参数中需要指出要访问的对象,即上例中的“m_FA.Msg(m_FB)”要访问的对象就是 m_FB
6)一个类的成员函数也可以是另一个类的友元

7)重载一些操作符时友元函数作用非常明显

 

 C++提供一种允许外部类和函数存取类的私有成员和保护成员的辅助方法,即将它们声明为一个给定类的友元(或友元函数),使其具有类成员函数的访问权限。但友元本身不是类的成员,它不属于任何类。

友元函数是能访问类的所有成员的普通函数,一个函数可以是多个类的友元函数,只需在各个类中分别声明。

将一个函数声明为某个类的友元函数的方法是在该类定义里提供一个以关键字friend开头的函数原型,友元函数的定义,可以在类的内部或外部,友元函数虽然是在类内进行声明,但它不是该类的成员函数,不属于任何类,在类外定义友元函数时,与普通函数的定义一样,不应在函数名前用类名加以限制,因此,友元函数不像成员函数那样在调用时使用对象名,友元函数要对类的成员进行访问,必须在参数表中显式指明要访问的对象。

C++不允许将构造函数、析构函数和虚函数声明为友元函数。

友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend,其格式如下: friend 类型 函数名(形式参数); 友元函数的声明可以放在类的私有部分,也可以放在公有部分,它们是没有区别的,都说明是该类的一个友元函数。 一个函数可以是多个类的友元函数,只需要在各个类中分别声明。 友元函数的调用与一般函数的调用方式和原理一致。

 

 

 

 

问题的提出

        我们已知道类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查等都需要时间开销,而影响程序的运行效率。

        为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。

        友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。

        友元函数

        友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,即在定义上和调用上与普通函数一样。下面举一例子说明友元函数的应用。

        #include
        #include

        class Point
        {
        public:
          Point(double xx, double yy) { x=xx; y=yy; }
          void Getxy();
          friend double Distance(Point &a, Point &b);
        private:
          double x, y;
        };

        void Point::Getxy()
        {
        cout<<"("<
        }

        double Distance(Point &a, Point &b)
        {
        double dx = a.x - b.x;
        double dy = a.y - b.y;
        return sqrt(dx*dx+dy*dy);
        }

        void main()
        {
        Point p1(3.0, 4.0), p2(6.0, 8.0);
        p1.Getxy();
        p2.Getxy();
        double d = Distance(p1, p2);
        cout<<"Distance is"<
        }

        说明:在该程序中的Point类中说明了一个友元函数Distance(),它在说明时前边加friend关键字,标识它不是成员函数,而是友元函数。它的定义方法与普通函数定义一样,而不同于成员函数的定义,因为它不需要指出所属的类。但是,它可以引用类中的私有成员,函数体中a.x,b.x,a.y,b.y都是类的私有成员,它们是通过对象引用的。在调用友元函数时,也是同普通函数的调用一样,不要像成员函数那样调用。本例中,p1.Getxy()和p2.Getxy()这是成员函数的调用,要用对象来表示。而Distance(p1,
      p2)是友元函数的调用,它直接调用,不需要对象表示,它的参数是对象。(该程序的功能是已知两点坐标,求出两点的距离。)

友元类

        友元除了前面讲过的函数以外,友元还可以是类,即一个类可以作另一个类的友元。当一个类作为另一个类的友元时,这就意味着这个类的所有成员函数都是另一个类的友元函数。

1、友元关系不具有传递性,如类B是类A的友元类,类C是类B的友元类,这并不意味着类C是类A的友元类;
2、友元关系是单向的,不具有对称性(交换性),即类B是类A的友元,不能得出类A也是类B的友元,友元关系必须看到显式的声明;
3、当希望一个类可以存取另一个类的私有成员时,可以将该类声明为另一个类的友元,友元类的所有成员函数都可视为该类的成员函数,能存取该类的私有成员和保护成员;
4、友元关系不能被继续;
5、友元类的格式:friend class 类名;

你可能感兴趣的:(C++友元 简述)