精华内容
下载资源
问答
  • 友元函数 友元 友元成员函数

    千次阅读 2018-05-07 22:34:40
    友元 一般来说,类内的私有数据对外不可见的,但在有些情况下,我们需要在类外对该类的私有数据进行访问,这就需要用到一种新技术——友元(friend),即在声明前...友元函数是指某些非类成员函数,但可以访问类...

    友元

    一般来说,类内的私有数据是对外不可见的,但在有些情况下,我们需要在类外对该类的私有数据进行访问,这就需要用到一种新技术——友元(friend),即在声明前添加关键字friend

    友元关系是单向的,即如果A是B的友元,但B不一定是A的友元;
    友元关系无传递性,即如果A是B的友元,B是C的友元,但A不一定是C的友元。


    1. 友元函数

    友元函数是指某些非类成员函数,但可以访问类内的私有数据。

    #include <iostream>
    using namespace std;
    
    class A {
    private:
        int data;
    public:
        A() : data(1) {}
        friend void show( const A& t );  //添加friend定义友元函数
    };  
    
    /* 友元函数在类外声明时不加friend */
    void show( const A& t ) {
        cout << "data = " << t.data << endl;  
    }
    
    int main(void) {  
        A a;
        show(a);  
    
        return 0;  
    }
    
    /*
    
    运行结果:
    data = 1
    
    */

    2. 友元类

    友元类是指若需要在类B中直接访问类A的私有数据,因此将B作为A的友元(在A中声明friend class B;)。
    友元类中的成员函数、私有数据都可以在另一个类中被使用(即类B中可以直接使用类A的私有数据等)

    class Tv {
    private: 
        int state;
    public: 
        friend class Remote;  //声明Remote为Tv的友元类
        enum{ Off, On };
    
        Tv( int s = Off ) : state(s) {}
        void onoff() { state = (state == On) ? Off : On; }
    };
    
    class Remote {
    public: 
        void onoff( Tv & t ) { t.onoff(); }
    };

    3. 友元成员函数

    友元成员函数是指类中的一个成员函数被定义为友元函数。
    与友元类不同的是,只有友元成员函数可以在另一个中被使用,其余函数都不可以。

    #include <iostream>
    using namespace std;
    
    class B;  //前向声明
    
    class A{
    private: 
        int a;
    public: 
        A() { a = 1; }
        void print( B & b );
    };
    
    /* 示例位置1 */
    
    class B{
    private: 
        int b;
    public: 
        B() { b = 6; }
        void print() { cout << b << endl; }
        friend void A::print( B & b );  //友元成员函数
    };
    
    /* 被定义为友元成员函数的函数必须在类外(另一个使用该函数的类后面)定义 */
    void A::print( B & b ) {
        cout << "b = " << b.b << endl;
    }
    
    int main() {
        A a;
        B b;
        a.print( b );
    
        return 0;
    }
    
    /*
    
    输出结果:
    b = 6
    
    */

    需要注意的是:
    (1)类的前向声明。由于在A中的print函数需要使用B,如果不进行B的前向声明,编译器就不知道B是一个类,会报错。
    (2)类的排列顺序。在类B中会用到A的方法print(),因此需要先定义A,再定义B。
    (3)友元成员函数的定义位置。友元成员函数不能使用内联代码,类中只能有函数声明。函数定义需要放到类之后,在类外进行定义,而且必须放到另一个类定义的后面。(对上面代码来说,若将A::print()的定义放在类B定义之前——示例位置1处,也会报错,提示类B未完成)

    对于友元的位置在何处生明,可以简单记为friend在哪,哪个就可以被外面直接访问。(friend在类A,A就可以被其他特定位置访问)

    展开全文
  • 1.友元函数需要在类中任意位置进行声明,跟普通函数声明不同的要加上friend 关键字,然后在类外进行实现,所以友元函数并不是类的成员函数。声明为友元函数之后,友元函数便可访问类中的私有成员。 2.友元函数没有...

    1.友元函数

    友元函数的一些特点:
    1.友元函数需要在类中任意位置进行声明,跟普通函数声明不同的是要加上friend 关键字,然后在类外进行实现,所以友元函数并不是类的成员函数。声明为友元函数之后,友元函数便可访问类中的私有成员。
    2.友元函数没有隐藏的this指针,故参数列表中要多一个类的参数,相当于this指针,但是不一定为第一个参数,这使得友元函数的操作更加灵活,能够完成一些成员函数无法完成的操作,使用友元函数将会使类的操作更加灵活。
    比如:

    class Complex
    {
    public:
    	Complex(int real = 0, int imag = 0) :m_real(real), m_imag(imag)
    	{}
    	~Complex()
    	{}
    	Complex operator+(int  a) {
    		return Complex(m_real + a, m_imag);
    	}
    private:
    	int m_real;
    	int m_imag;
    };
    
    void main()
    {
    	Complex c, c1(1, 3);
    	c = c1 + 10;
    	//c = 10 + c1;  
    }
    

    这里我们通过运算符重载+号实现了Complex + int 即c = c1 + 10; ,编译器可以运行通过;
    但是如果想实现int +Complex 即//c = 10 + c1; 的话,还是需要对+号进行运算符重载,重新解释+号的含义,但是由于类中的成员函数第一个参数默认为自身类型this,按照c = 10 + c1这样赋值运算的话,相当于调动10.operator(c1),10并不是一个对象,无法给Complex operator+(int a)函数中的this指针传参,无法编译通过。
    那么如何解决上面的问题呢?这就需要用友元函数来实现了:

    
    class Complex
    {
    	friend Complex operator+(int val, const Complex& c);  //将函数声明为友元函数,加friend关键字
    	friend Complex operator+(const Complex& c1, const Complex& c2);
    public:
    	Complex(int real = 0, int imag = 0) :m_real(real), m_imag(imag)
    	{}
    	Complex& operator=(const Complex& c)
    	{
    		if (this != &c)
    		{
    			m_real = c.m_real;
    			m_imag = c.m_imag;
    		}
    		return *this;
    	}
    	~Complex()
    	{}
    	Complex operator+(int  a) {
    		return Complex(m_real + a, m_imag);
    	}
    private:
    	int m_real;
    	int m_imag;
    };
    
    Complex operator+(int val, const Complex& c)
    {
    	return Complex(val + c.m_real, c.m_imag);   //友元函数可以访问到类中的私有成员。
    }
    
    Complex operator+(const Complex& c1, const Complex& c2)
    {
    	return Complex(c1.m_real + c2.m_real, c1.m_imag + c2.m_imag);
    }
    
    void main()
    {
    	Complex c, c1(1, 3), c2(2, 5);
    	c = c1 + 10;
    	c = 10 + c1;
    	c = c1 + c2;
    }
    

    在这里插入图片描述
    3.友元函数和static成员函数都没有this指针,static成员函数调动的优先级会比友元函数高。
    4.友元函数不能用const修饰,友元函数的调用与普通函数的调用和原理相同。
    5.一个函数可以是多个类的友元函数

    class Stu;   //前向声明
    class Test;
    
    class Test
    {
    	friend void fun(const Test &t, const Stu &s);
    public:
    	Test()
    	{
    	}
    private:
    	int m_a = 0;  //默认值
    	int m_b = 0;
    };
    class Stu
    {
    	friend void fun(const Test &t, const Stu &s);
    public:
    	int m_x = 0;
    	int m_y = 0;;
    };
     void fun(const Test &t, const Stu &s)  //fun()既是class Test也是class Stu的友元函数
    {}
    void main()
    {
    	Test t;
    }
    

    2.友元类

    友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。

    特点:
    1.友元关系是单向的,不具有交换性。
    比如下面的例子有Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
    2.友元关系不能传递
    如果B是A的友元,C是B的友元,则不能说明C时A的友元。、

    
    class Date; // 前置声明
    class Time
    {
    	friend class Date; // 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量
    public:
    	Time(int hour, int minute, int second)
    		: _hour(hour)
    		, _minute(minute)
    		, _second(second)
    	{}
    private:
    	int _hour;
    	int _minute;
    	int _second;
    };
    
    class Date
    {
    public:
    	Date(int year = 1900, int month = 1, int day = 1)
    		: _year(year)
    		, _month(month)
    		, _day(day)
    		,_t(9,30,45)
    	{}
    	void SetTimeOfDate(int hour, int minute, int second)
    	{
    		// 直接访问时间类私有的成员变量
    		_t._hour = hour;
    		_t._minute = minute;
    		_t._second = second;
    	}
    private:
    	int _year;
    	int _month;
    	int _day;
    	Time _t;
    };
    
    void main()
    {
    	Time t1(11,2,3);
    	Date d1(2020,3,15);
    	Date d2 = d1;
    	d1.SetTimeOfDate(1, 10, 11);
    }
    
    
    

    运行结果

    展开全文
  • 但是类之间的关系不一定是继承,有时一个类需要访问另一个类的成员/成员函数,或者一个函数需要访问类中的成员。于是友元(friend)机制诞生了。通常类之间的问题用友元类解决,友元函数常用在运算符重载等场景。一...

    212896cf12b66b6f41b8e4c8f052389b.png

    这一章的问题从”如何畅通无阻的访问另一个类“开始,类的属性有private、protected、public,根据继承权限有不同的访问方式。但是类之间的关系不一定是继承,有时一个类需要访问另一个类的成员/成员函数,或者一个函数需要访问类中的成员。于是友元(friend)机制诞生了。通常类之间的问题用友元类解决,友元函数常用在运算符重载等场景。

    一、友元函数

    友元函数既可以是类外函数,也可以是其他类的成员函数。将非成员函数声明为友元函数,请看下面的例子:

    #include 

    那么,其他类的成员函数如何处理呢?

    #include 
    注意两点:一、先声明了Address类,因为接下来的Home类会用到它,如果不提前声明,编译器会报错。二、Address类的声明在Home类的声明和实现的中间,因为Home类的成员函数用到了Address类的成员,如果不能提前知道Address类的具体声明内容,编译器也会报错。

    二、友元类

    不多说,把上面的例子改一改:

    #include 

    不仅可以将一个函数声明为一个类的“朋友”,还可以将整个类声明为另一个类的“朋友”,这就是友元类。友元类中的所有成员函数都是另外一个类的友元函数。例如将类 B 声明为类 A 的友元类,那么类 B 中的所有成员函数都是类 A 的友元函数,可以访问类 A 的所有成员,包括 public、protected、private 属性的。

    关于友元,有三点需要说明:

    1. 友元关系是单向的,不是双向的。如果声明了类 B 是类 A 的友元类,不等于类 A 是类 B 的友元类,类 A 中的成员函数不能访问类 B 中的 private 成员。
    2. 友元的关系不能传递。如果类 B 是类 A 的友元类,类 C 是类 B 的友元类,不等于类 C 是类 A 的友元类。
    3. 除非有必要,一般不建议把整个类声明为友元类,而只将某些成员函数声明为友元函数,这样更安全一些。

    (如有转载请注明作者与出处,欢迎建议和讨论,thanks)

    展开全文
  • C++ 友元函数和友元

    2013-05-20 17:09:00
    友元关系提供了不同类或对象的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制。通俗地说,友元关系就是一个类主动声明哪些其他类或函数它的朋友,进而给他们提供对本类的访问特许。也就是说,用过...

    1、友元函数

    友元关系提供了不同类或对象的成员函数之间、类的成员函数与一般函数之间进行数据共享的机制
    通俗地说,友元关系就是一个类主动声明哪些其他类或函数是它的朋友,进而给他们提供对本类的访问特许。也就是说,用过友元关系,一个普通函数或者类的成员可以访问封装于另外一个类中的数据。从一定程度上讲,友元是对数据隐蔽和封装的破坏。但是为了数据共享,提高程序的效率和可读性,很多情况下这种小的破坏也是必要的
    使用友元函数计算两点间的距离:

    #include <iostream>
    #include <math.h>
    using namespace std;
    
    class Point
    {
    public:
        Point(int xx=0,int yy=0)
        {
            X = xx;
            Y = yy;
        }
        int GetX()
        {
            return X ;
        }
        int GetY()
        {
            return Y;
        }
        friend float fDist(Point &a,Point &b);
    private:
        int X,Y;
    };
    
    
    float fDist(Point &p1,Point &p2)
    {
        double x = double(p1.X-p2.X);
        double y = double(p1.Y-p2.Y);
        return float(sqrt(x*x + y*y));
    }
    int main(int argc, char* argv[])
    {
        Point myp1(1,1),myp2(4,5);
        
        cout<<"The distance is:";
        cout<<fDist(myp1,myp2)<<endl;
        return 0;
    }

    运行结果:The distance is:5
    友元函数是在类中用关键字friend修饰的非成员函数。

    2、友元类

    声明友元类,是建立类与类之间的联系,实现类之间数据共享的一种途径。若A类为B类的友元类,则A类的所有成员都是B类的友元函数,都可以访问B类的私有和保护成员。
    第一、友元关系是不能传递的。B类是A类的友元,C类是B类的友元,C类和A类之间,如果没有声明,就没有任何友元关系,不能进行数据共享。
    第二、友元关系是单向的。如果声明B类是A类的友元函数,B类的成员函数就可以访问A类的私有和保护数据,但A类的成员函数却不能访问B类的私有和保护数据。
    第三、友元关系是不被继承的。如果类B是A类的友元,类B的派生类并不会自动成为类A的友元。打个比方,就好像别人信任你,但不见得信任你的孩子。

    #include <iostream>
    using namespace std;
    
    class A
    {
        friend class B;
    public:
        void Display()
        {
            cout<<"I'm at A"<<endl;
            cout <<x<<endl;
        }
    private:
        int x;
    };
    
    class B
    {
    public:
        void Set(int i);
        void Display();
    private:
        A a;
    };
    
    void B::Set(int i)
    {
        a.x=i;
    }
    
    void B::Display()
    {
        cout <<"I'm at B"<<endl;
        a.Display();
    }
    
    int main(int argc, char* argv[])
    {
        B b;
        b.Set(99);
        b.Display();
        return 0;
    }

    运行结果:I‘ m B
           I'm A
                  99

    转载于:https://www.cnblogs.com/haoyuanyuan/archive/2013/05/20/3088925.html

    展开全文
  • 一个类定义了友元函数友元类可以访问这个类的所有成员,包括私有的,也就是说···是类的朋友,我去,这个类是女朋友类啊,什么都可以访问,什么隐私都没有了。
  • 一、友元函数  1、友元函数允许在类外访问该类中的任何成员,使用关键字friend说明... 友元函数不属于该类的成员函数,它定义在类外的普通函数,只是在类中通过friend关键字声明,从而使该函数可以访问类中的pr...
  • 友元函数是指某些函数或者变量,虽然不是类内的成员却能够访问类的所有成员的函数。类授予它的友元特别的访问权。实现类内数据共享,减少开销,提高效率。 注意的是友元函数是可以访问类内的的私有成员。但是,...
  • 友元函数

    2020-05-06 21:27:10
    如果A声明为B友元,那么A所有成员函数都自动成为B的友元函数。 A是B朋友,那么A一家人都是B好朋友 友元关系是单向传递 A是B好朋友,但B并不一定是A好朋友 友元关系不具有传递性 也就是说C...
  • 友元函数提供了不同类或对象的成员函数之间、类的成员函数和一般函数之间进行数据共享的机制。通俗的说,友元关系就是一个类主动声明哪些类或函数它的朋友,进而给它们提供对本类的访问特性。也就是说,通过友元...
  • 错误(活动) 后面有“::”名称一定是类名或命名空间名 test0 c:\Users\Administrator\Documents\Visual Studio 2015\Projects\test0\test0\Screen.h 9 严重性 代码 说明 项目 文件 行 错误 C2027 使用了未定义类型...
  • 运算符重载为成员函数,第一个参数必须是本类的对象。而<<和>>的第一个操作数一定是ostream类型,所以<<只能重载为友元函数。 (1) 只能为友元 >> ( 输入流操作 ) << ( 输出流...
  • 友元函数 自考教材中简单介绍 (2008版教材P109)友元函数可以存取私有成员、公有成员和保护成员。...这种友元关系也不具有交换性,即当说明类A是类B友元时,类B不一定是类A友元。 目录 友元函数 1.友...
  • 关于青春 一张张执着的面孔和奋不顾身的借口~ 目录: 1.static成员 概念 特性 成员初始化 ...2.友元函数 ...用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在外进行初始化。 1...
  • 友元”的概念其实针对于类的私有成员来说的,一个类的由于封装的缘故,类体中私有成员是不可以被外界访问的,无论继承也好,都无法访问类内私有成员的。但是正是有那么一些人,愿意打破陈规破例访问类体内的...
  • 友元函数(friend)

    2014-06-17 03:49:08
    类的外部,也就是通过实例来访问私有(private)或保护(protected)成员,这被禁止的。但从实用性来说,的确有时很需要...友元函数必须在类里面申明,而且友元函数一定不是该类的成员函数。因此,这样的“特权”实际上已
  • 如果重载双目操作符(即为类的成员函数),就只要设置一个参数作为右侧运算量,而左侧运算量就是对象本身。。。。。。而 >> 或左侧运算量 cin或cout 而不是对象本身,所以不满足后面一点。。。。。。。。就只能...
  • 友元函数是C++中的一种机制,它不属于类的成员函数,但是可以访问到类的私有变量,因此,它在一定程度上破坏了封装的特性。 class T { public: T(int a, int b): _a(a), _b(b) { } firend void Change(T&...
  • /* ... *All rights reserved. *文件名称:main.cpp ... *问题描述:定义下面两个类的成员函数(为体验友元类,实际上本例并不一定是一个好的设计,将两个类的合并为一个DateTime,日期、时间都处理更好) *输入描述:
  • 如果重载双目操作符(即为类的成员函数),就只要设置一个参数作为右侧运算量,而左侧运算量就是对象本身。。。。。。而 >> 或<< 左侧运算量 cin或cout 而不是对象本身,所以不满足后面一点。。。。...
  • 如果重载双目操作符(即为类的成员函数),就只要设置一个参数作为右侧运算量,而左侧运算量就是对象本身。。。。。。 而 >> 或。。。。。。。。就只能申明为友元函数了。。。 如果一定要声明为成员函数,只能...
  • 类A一定是类C的友元 B.类C的成员函数可以访问类B的对象的任何成员 C.类A的成员函数可以访问类B的对象的任何成员 D.类C一定是类A的友元 答案:C 友元类是单向的(不可逆),也不传递(A须通过B的成员函数才能访问C) ...
  • 如果重载双目操作符(即为类的成员函数),就只要设置一个参数作为右侧运算量,而左侧运算量就是对象本身 而 &amp;gt;&amp;gt; 或&amp;lt;&amp;lt; 左侧运算量 cin或cout 而不是对象本身,所以...
  • (1)成员函数在类外定义时,因为函数体还有形参列表都出现在成员名之后,都在类作用域内定义,所以不用加域作用符 来引用其他的成员。 (2)函数的返回值不一定需要在类的作用域中,但是若是返回类中定义的...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 180
精华内容 72
关键字:

友元函数一定是类的成员函数