精华内容
下载资源
问答
  • C++友元函数

    2019-04-11 13:42:47
    1.友元函数是什么? 将一个函数在类内声明为该类的友元,那么这个函数就叫这个类的友元函数;友元函数有访问类内私有成员的权限。 友元函数不属于类,但有访问私有的权限 2.friend关键字 通过friend关键字,可以...

    友元函数

    1.友元函数是什么?

    将一个函数在类内声明为该类的友元,那么这个函数就叫这个类的友元函数;友元函数有访问类内私有成员的权限。

    友元函数不属于类,但有访问私有的权限

    2.friend关键字

    通过friend关键字,可以将一个函数声明为一个类的友元。

    class className{
        ...
        friend typeName function (args);
        ...
    };
    

    类内声明为友元函数,在类外定义即可

    typeName function (args){
        ...  
    }
    

    3.重载 << 运算符

    为了方便自定义类的输出,我们可以重载<<运算符(相当于Java中重载toString()方法)。因为<<是ostream类的成员运算符函数,我们总不能去修改库函数,所以我们必须在外部声明一个适用于自定义类的函数,然后将其声明为友元函数

    为什么不在自定义类中声明?类中声明的运算符函数,左操作数是调用对象,但是 << 运算符的做操作数是ostream的对象。

    class Int {
    private:
        int data;
    public:
        Int(int x = 0);
        friend std::ostream &operator << (std::ostream &out, Int &obj);
    };
    
    std::ostream &operator << (std::ostream &out, Int &obj){
        out << "这个整数是 " << obj.data << std::endl;
        return out;
    }
    

    这里可以用obj.data直接访问私有成员,因为,obj对象的类的友元函数

    int main() {
        using std::cout;
        using std::endl;
        Int a(3);
        cout << a << endl;
        return 0;
    }
    

    cout << a; 等价于 operator(cout, a);

    为什么返回ostream的引用?

    如果不返回,cout << a 返回void,然后执行void << endl,并没有定义 operator(void, endl)这样的函数,所以,cout << a << endl就无法执行了。

    返回引用,cout << a 返回 cout,然后再进行cout << endl;

    展开全文
  • 友元函数

    2021-02-02 10:58:19
    什么要使用友元函数 当类想要实现一个功能,而他本身又完成不了的时候,需要借助外力来完成,这时候设置一个友元函数来完成.友元函数拥有类的一切权限,提高了执行效率 友元函数的俩种使用方式 友元函数,友元类 使用...

    为什么要使用友元函数

    当类想要实现一个功能,而他本身又完成不了的时候,需要借助外力来完成,这时候设置一个友元函数来完成.友元函数可以访问类里的所有数据,提高了执行效率

    友元函数的俩种使用方式

    友元函数,友元类

    使用全局函数作为友元函数

    这里设计了一个CPU升级的函数,因为电脑本身是无法自己给自己升级的,所以就要借助外力,当然也可以定义接口写

    这里的实现友元函数也很简单,只要把声明放入类里就行,public和private都一样

    #include <iostream>
    #include <string>
    #include <sstream>
    
    //把全局函数设为友元函数
    //设一个升级CPU的函数
    class computer
    {
    public:
    	computer();
    	std::string description();
    	friend void upgrade(computer* computer);
    private:
    	std::string CPU;
    
    };
    
    computer::computer()
    {
    	this->CPU = "i7";
    }
    
     std::string computer:: description() {
    	 std::stringstream ret;
    	 ret << "CPU:" << CPU;
    	 return ret.str();
    }
    
     void upgrade(computer *computer) {
    	 computer->CPU = "i9";
     }
    int main() {
    	computer com;
    	std::cout << com.description() << std::endl;
    
    	upgrade(&com);
    	std::cout<<com.description()<<std::endl;
    
    	system("pause");
    	return 0;
    }
    

    使用类的成员函数作为友元函数

    这里再写函数时遇到几个问题,因为为了方便复制过来,我没有把类和方法以及main函数分开写,不知道问题是不是出现在这

    1.先定义的类的成员函数才可以在后定义的类里 作为成员函数
    2.因为上面那点,所以先定义的类的成员函数可能会引用下面的类,所以要在前面先申明,比如我写的 class computer,

    如果涉及到具体方法还要添加头文件
    在这里插入图片描述

    #include <iostream>
    #include <string>
    #include <sstream>
    
    //把类的成员函数设为友元函数
    //设一个升级CPU的函数
    class computer;
    
    class computerServe 
    {
    public:
    	void upgrade(computer* computer);
    private:
    	std::string CPU;
    };
    
    class computer
    {
    public:
    	computer();
    	std::string description();
    	friend void computerServe::upgrade(computer* computer);
    
    private:
    	std::string CPU;
    	
    };
    computer::computer()
    {
    	this->CPU = "i7";
    }
    
     std::string computer:: description() {
    	 std::stringstream ret;
    	 ret << "CPU:" << CPU;
    	 return ret.str();
    }
    
    
     void computerServe::upgrade(computer *computer) {
    	 computer->CPU = "i9";
     }
    
    int main() {
    	computer com;
    	computerServe serve;
    
    	std::cout << com.description() << std::endl;
    
    	serve.upgrade(&com);
    	
    	std::cout<<com.description()<<std::endl;
    
    	system("pause");
    	return 0;
    }
    
    
    
    
    展开全文
  • 友元为什么需要友元get/set Method为什么使用友元关系辨别同类间无私处异类间有友元友元不是成员友元函数全局函数作友元语法格式实战操练:求两点之间的距离类的成员函数作友元语法格式实战操练:求两点之间的距离前...

    友元

    为什么需要友元

    get/set Method

    get 方法和 set 方法,是常见的获取和设置类内数据成员的方式。比如游戏角色遭到对方攻击后血量减少,就需要用到 set 方法,而要实时的显示就需要 set 方法。

    我们先给出例子:

    #include <iostream>
    
    using namespace std;
    
    class Sprite    //设置角色类
    {
    public:
        Sprite(int lb = 100) :_lifeBlood(lb) {}  //构造角色血量
        
        int getLiseBlood()     //返回当前血量
        {
            return _lifeBlood;
        }
    
        void setLiseBlood(int lb)    //设置遭到攻击之后的血量
    	{
            _lifeBlood = lb;      
        }
    
    private:
        int _lifeBlood;      //定义角色血量
    };
    
    void fight(Sprite & sp)  //参加战斗
    {
        sp.setLiseBlood(sp.getLiseBlood() - 20);    //修改受到攻击变化之后的剩余血量
        cout << sp.getLiseBlood() << endl;    //打印变化之后的血量
    
    }
    int main()
    {
        Sprite sp;		//生成类对象
        fight(sp);		//全局函数调用
        return 0;
    }
    

    运行结果为:

    运行结果

    上面实现是没有问题的,但是效率很低,假设一下很多游戏里面,角色受到了万箭穿心的伤害,就会频繁的使用set方法和get方法。调用函数就会频繁的压栈出栈。那么我们就需要做一些提高效率的工作。

    如果我们对于fight函数进行修改:

    void fight(Sprite & sp)  //参加战斗
    {
        //sp.setLiseBlood(sp.getLiseBlood() - 20);    //修改变化之后的剩余血量
        //cout << sp.getLiseBlood() << endl;    //输出血量
    
        //提高效率的方法
        sp._lifeBlood = sp._lifeBlood - 20;  
        //_lifeBlood 是类内私有成员不允许外部访问
        cout << sp._lifeBlood << endl;
    }
    

    上面使用方法直接访问类内私有成员而不通过类内函数成员。
    上面的使用方法必须调用函数是类内函数成员才能访问类内私有数据成员,但是fight函数是全局函数,所以还是无法直接访问类内的私有数据成员。

    我们也不会把fight函数放到类内,因为fight函数可能需要操作多个角色,fight函数的形参是可以变化的根据当时参加战斗的人数来决定的,所以一般不写到类内。那么如果提高效率呢,就需要用到友元。

    fight 全局接口,通过战斗来参加或是减少血量,对于这种频繁的操作,可以每次不通过对象,而直接操作。

    方法很简单,将函数 fight 设置为类 Sprite 的友元函数。

    通过友元这层关系,就可以直接访问类的私有数据成员,从面大大提高的访问的效率。

    我们在之前的操作中想要访问类内的私有成员,就必须使用成员函数,现在全局函数也需要去访问,我们就使用友元。

    实现代码:

    #include <iostream>
    
    using namespace std;
    
    class Sprite    //设置角色类
    {
        friend void fight(Sprite & sp);   //将函数 fight 设置为类 Sprite 的友元
        
    public:
        Sprite(int lb = 100) :_lifeBlood(lb) {}  //构造角色血量
        
        int getLiseBlood()     //返回当前血量
        {
            return _lifeBlood;
        }
    
        void setLiseBlood(int lb)    //设置遭到攻击之后的血量
    	{
            _lifeBlood = lb;      
        }
    
    private:
        int _lifeBlood;      //定义角色血量
    
    };
    
    void fight(Sprite & sp)  //参加战斗
    {
        //sp.setLiseBlood(sp.getLiseBlood() - 20);    //修改变化之后的剩余血量
        //cout << sp.getLiseBlood() << endl;    //输出血量
    
        //提高效率的方法
        sp._lifeBlood = sp._lifeBlood - 30;
        cout << sp.getLiseBlood() << endl;
    
    }
    int main()
    {
        Sprite sp;
        fight(sp);
        return 0;
    }
    

    运行结果为:

    使用友元直接访问私有数据成员实现血量变化

    get方法和set方法是标准封装的结果,但是上面使用友元会破环这种封装,但是又带来了效率的提高,所以被留存下来并且在一些地方有广泛的应用。

    为什么使用友元

    采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有,依此提供类与外界间的通信接口。

    但是,有时需要定义一些函数,这些函数不是类的一部分但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该类的友元函数。除了友元函数外,还有友元类,两者统称为友元。

    友元的作用是提高了程序的运行效率(即减少了类型和安全性检查及调用的时间开销)。

    但它破坏了类的封装性和隐藏性,带来了效率的提高,这种破坏也不是全面性的破坏,是通过类授权许可的,并不是完全性的破坏,又能提高效率,使得非类内的函数可以访问类的私有数据成员。

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

    关系辨别

    同类间无私处

    一个类生成的对象可以访问本类生成的所有对象的私有成员。

    先前,我们自实现 mystring 的时候,发现other._str,我们直接使用了,要知道_str 是 mystring 类的私有成员。为什么没有报错呢?

    因为他们属于同类间的访问,所以 private 对其没有限制。
    例如我们前面博客实现的mystring:

    mystring::mystring(const mystring & other)
    {
    	int len = strlen(other._str);
    	this->_str = new char[len+1];
    	strcpy(this->_str,other._str);
    }
    

    当前对象就可以直接访问同一类生成其他对象的私有成员。

    异类间有友元

    但是,如果两个对象不是发生在同一类生成,就麻烦了。private 属性会限制类对象私有成员的访问。

    struct 对象其成员默认是 public 的,所以 operator+函数中是可以成立的,但是 struct换为 class 后,其成员默认是 private 的,就会编译出错。

    若不想通过 get/set 方法来获取私有成员,怎么办呢,答案是友元。

    使用struct通过+运算符重载实现;

    #include <iostream>
    
    using namespace std;
    
    struct Comlpex
    {
        double real;
        double image;
    };
    
    Comlpex operator+(Comlpex& c1, Comlpex& c2)
    {
        Comlpex tmp;
        tmp.real = c1.real + c2.real;
        tmp.image = c1.image + c2.image;
        return tmp;
    }
    
    int main()
    {
        Comlpex c1 = { 1,2 }, c2 = { 3,4 };
        Comlpex sum = { 0,0 };
        sum = c1 + c2;
        return 0;
    }
    

    在class中使用友元实现+运算符重载。

    #include <iostream>
    
    using namespace std;
    
    class Comlpex
    {
        friend  Comlpex operator+(Comlpex & c1, Comlpex & c2);  //声明友元函数
    public:
        Comlpex(double r = 0, double i = 0):real(r), image(i) {}  //构造器
        
        void DumpFromat()
        {
            cout << "(" << real << "," << image << ")" << endl;
        }
    
    private:
        double real;
        double image;
    };
    
    //通过对象传递this,不能越过对象直接访问类内私有数据成员
    Comlpex operator+(Comlpex& c1, Comlpex& c2)
    {
        Comlpex tmp;
        tmp.real = c1.real + c2.real;
        tmp.image = c1.image + c2.image;
        return tmp;
    }
    
    int main()
    {
        Comlpex c1(1,2), c2(3,4);
        Comlpex sum = { 0,0 };
        sum = c1 + c2;
        sum.DumpFromat();
        return 0;
    }
    

    运行结果为:

    运行结果

    友元不是成员

    友元函数终究不是成员函数,成员中有隐参 this 指针,可以直接访问成员,而友元中则没有,不能通过this指针访问,必须得通过对象来访问。
    类内函数也是通过对象的this指针访问类内的私有成员,而不是直接访问。

    友元仅是打破了外部访问中的 private 权限。
    声明为谁的友元,就可以通过谁的对象 ,访问谁的私有成员。

    友元函数

    友 元 的 声 明 位 置 , 可 以 是 类 中 任 意 位 置 , 且 其 声 明 不 受 访 问 权 限 关 键 字(public/protected/private)的 影 响。

    全局函数作友元

    全局函数作友元,只需要在相应的类内作友元函数声明即可。一个函数可以是多个类的友元函数,只需要在各个类中分别声明。

    语法格式

    class A
    {
    friend void globalfunction(A &,...)
    public:
    .... 
    }
    

    实战操练:求两点之间的距离

    #include<iostream>
    #include<cmath>
    using namespace std;
    
    class Point
    {
    friend double distance(Point &a, Point &b);   //声明友元
    public:
    	Point(double x = 0,double y = 0):_x(x),_y(y){}		//构造器
    	void getFormatxy();		//类内成员函数声明
    
    private:
    double _x, _y;
    };
    
    
    void Point::getFormatxy()	//类内成员函数实现
    {
    cout <<"(" << _x << "," << _y << ")" <<endl;
    }
    
    double distance(Point & a, Point & b)	//计算两点之间的举例
    {
    	double dx = a._x - b._x;
    	double dy = a._y - b._y;
    	return sqrt(dx*dx + dy*dy);
    }
    
    
    int main(void)
    {
    	Point p1(3.0,4.0), p2(6.0,8.0);
    	p1.getFormatxy();
    	p2.getFormatxy();
    	double d = distance(p1, p2);
    	cout<< "distance is " << d <<endl;
    	return 0;
    }
    

    运行结果为:

    求两点距离

    类的成员函数作友元

    一个类的成员函数作友员,在声明为另一个类的友元时,要将原类的作用域加上,其它属性同全局函数。

    语法格式

    class A
    {
    friend void One::globalfunction(A&,...);
    public:
    ...
    }
    

    实战操练:求两点之间的距离

    #include<iostream>
    #include<cmath>
    using namespace std;
    
    class Point;	//前向声明
    
    class ManagerPoint
    {
    public:
    	//ManagerPoint类内普通函数成员声明
    	double distance(Point &a, Point &b);	
    
    };
    
    
    class Point
    {
    //声明友元函数
    friend double ManagerPoint::distance(Point & a, Point & b);    
    
    public:
    Point(double x, double y):_x(x),_y(y){}		//构造器
    
    void getFormatxy();			//Point类内普通函数成员声明
    
    private:
    double _x, _y;
    };
    
    void Point::getFormatxy()		//Point类内普通函数成员实现
    {
    cout << "(" << _x << "," << _y << ")" << endl;
    }
    
    //ManagerPoint类内普通函数成员实现
    double ManagerPoint::distance(Point & a, Point & b)
    { 
    	double dx = a._x - b._x;
    	double dy = a._y - b._y;
    	return sqrt(dx*dx + dy*dy);
    }
    
    int main(void)
    {
    	Point p1(3.0, 4.0), p2(6.0, 8.0);
    	p1.getFormatxy();
    	p2.getFormatxy();
    	ManagerPoint mp;
    	float d = mp.distance(p1,p2);
    	cout << "distance is" << d<< endl;
    	return 0;
    }
    

    运行结果为:

    类的成员函数做友元

    我们可以看到实现了相同的功能。
    上面的代码得以实现是因为存在前向声明。

    前向声明

    前向声明,是一种不完全型(incomplete type)声明,即只需提供类名(无需提供类实现)即可。

    正因为是类型不完全,功能也很有限:不能定义对象,可以定义指针和引用做参数或者返回值,用作函数声明。
    前向声明

    指针和引用都是指针,指针和引用的大小均是 4 字节,对于编译器来说是可以确定的,但是对于一个不完类型编译器是无法确定其大小的。所以上例中的 distance(Point &a, Point &b)中的引用改为 distance(Point a, Point b)是不可行的。若改为指针类型,distance(Point *a, Point *b)则是可行的。前向声明常见于头文件中,而在其头文件所在的 cpp 文件中被包含。

    友元类

    当一个类中所有成员函数,希望均可访问另一个类的私有成员时,可以将该类声明为另一类的友元类。

    友元类,导致封装破坏的面积扩大化,但由于其简易操作的特性,而常常在实际开发中被使用。

    声明

    class A
    {
    	friend class B;
    public:
    
    private:};
    

    应用:求两点之间的距离

    #include<iostream>
    #include<cmath>
    using namespace std;
    
    class Point
    {
    	friend class ManagerPoint;		//声明有元类
    public:
    	Point(double x, double y)		//构造器
    	{
    		_x = x;
    		_y = y;
    	}
    	void getFormatxy();			//Point类内普通函数声明
    private:
    	double _x, _y;
    };
    
    void Point::getFormatxy()		//Point类内普通函数实现
    {
    	cout << "(" << _x << "," << _y << ")" << endl;
    }
    
    class ManagerPoint		
    {
    public:
    	double distance(Point& a, Point& b);	//ManagerPoint	类内函数成员声明
    };
    
    double ManagerPoint::distance(Point& a, Point& b)//ManagerPoint	类内函数成员声明
    {
    	double dx = a._x - b._x;
    	double dy = a._y - b._y;
    	return sqrt(dx * dx + dy * dy);
    }
    
    int main(void)
    {
    	Point p1(3.0, 4.0), p2(6.0, 8.0);
    	p1.getFormatxy();
    	p2.getFormatxy();
    	ManagerPoint mp;
    	float d = mp.distance(p1, p2);
    	cout << "distance is" << d << endl;
    	return 0;
    }
    

    运行结果为:
    运行结果

    应用:求三点构成的面积

    上面运行结果没有问题,但是一但使用友元类,相当于之前友元函数撕开的小口子用友元类破坏性更大,从逻辑上友元类应该少用,但是实际工作中,我们进程会使用友元类,因为比较简单方便。

    上面代码假设在 ManagerPoint 中再加一个函数成员,求三点的面积。doubel area(Point &a,Point &b, Point &c);是否一个友元类就可以搞定了呢?
    那么知道了三个点的距离就可以使用海伦公式求三角形面积。

    #include<iostream>
    #include<cmath>
    
    using namespace std;
    
    class Point
    {
    	friend class ManagerPoint;		//声明友元类
    public:
    	Point(double x, double y)		//构造器
    	{
    		_x = x;
    		_y = y;
    	}
    	void getFormatxy();			//Point类内普通函数声明
    private:
    	double _x, _y;
    };
    
    void Point::getFormatxy()		//Point类内普通函数实现
    {
    	cout << "(" << _x << "," << _y << ")" << endl;
    }
    
    class ManagerPoint			
    {
    public:
    	//类内普通函数声明
    	double distance(const Point& a, const Point& b);
    	//类内普通函数声明
    	double getArea(const Point& a, const Point& b, const Point& c);
    };
    
    //ManagerPoint	类内函数实现
    double ManagerPoint::distance(const Point& a, const Point& b)
    {
    	double dx = a._x - b._x;
    	double dy = a._y - b._y;
    	return sqrt(dx * dx + dy * dy);
    
    }
    
    //ManagerPoint	类内函数实现
    double ManagerPoint::getArea(const Point& a, const Point& b, const Point& c)
    {
    	double dx = distance(a, b);
    	double dy = distance(b, c);
    	double dz = distance(a, c);
    	double p = (dx + dy + dz) / 2;
    	return sqrt(p * (p - dx) * (p - dy) * (p - dz));
    }
    
    int main(void)
    {
    	Point p1(0.0, 0.0), p2(4.0, 0.0), p3(0.0, 4.0);
    	p1.getFormatxy();
    	p2.getFormatxy();
    	p3.getFormatxy();
    	ManagerPoint mp;
    	cout << "area is" << mp.getArea(p1,p2,p3) << endl;
    	return 0;
    }
    

    运行结果为:

    运行结果

    小结

    声明位置
    友元声明以关键字 friend 开始,它只能出现在类定义中。因为友元不是类授权的成员,所以它不受其所在类的声明区域 public private 和 protected 的影响。通常我们选择把所有友元声明组织在一起并放在类头之后。具体放的位置,要看团队的一致风格。

    友元利弊
    友元不是类成员,但是它可以通过对象访问类中的私有成员。友元的作用在于提高程序的运行效率,但是破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。不过类的访问权限确实在某些应用场合显得有些呆板,从而容忍了友元这一特语法现象。

    注意事项

    友元关系不能被继承。
    友元关系是单向的,不具有交换性。若类 B 是类 A 的友元,类 A 不一定是类 B 的友元,要看在类中是否有相应的声明。
    友元关系不具有传递性。若类 B 是类 A 的友元,类 C 是类B 的友元,类 C 不一定是类A 的友元,同样要看类中是否有相应的声明。

    最重要的思想:
    声明为谁的友元就可以通过谁的对象访问谁的私有成员。

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

    2017-03-07 15:15:31
    友元函数是什么呢?顾名思义“友元”,朋友的元素,那么大家都可以共享啦,这也就是友元的作用。 在C++中友元函数允许在类外访问该类中的任何成员,就象成员函数一样,友元函数用关键字friend说明。 那么问题...

                    C++友元函数

    友元函数是什么呢?顾名思义“友元”,朋友的元素,那么大家都可以共享啦,这也就是友元的作用。

    在C++中友元函数允许在类外访问该类中的任何成员,就象成员函数一样,友元函数用关键字friend说明。

    那么问题来了,为什么会需要友元函数和友元类呢??

    类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问
    私有成员的。非成员函数可以访问类中的公有成员,但是如果将数据成员都定义为公有的,这又破坏了隐藏
    的特性。另外,应该看到在某些情况下,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和
    安全性检查等都需要时间开销,而影响程序的运行效率。
      为了解决上述问题,提出一种使用友元的方案。友元是一种定义在类外部的普通函数,但它需要在类体
    内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。友元不是成员函数,但是
    它可以访问类中的私有成员。友元的作用在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,
    使得非成员函数可以访问类的私有成员。
      友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类。
      友元函数的特点是能够访问类中的私有成员的非成员函数。友元函数从语法上看,它与普通函数一样,
    即在定义上和调用上与普通函数一样。
    下面是我写的一个例子,分析一下友元函数~:

    首先我定义了一个Date类,然后分别为它初始化私有成员年月日,我在类中重载一个“<<”运算符,我想让它
    直接可以输出Date的私有成员(这里有一个小问题,在类中当你调用这个运算符时写法与平时不同有些别扭)
    ,所以我又在类外重载相同的运算符(这里定义时,就是平时使用cout<<d1的方式),然后通过使用友元函数
    的概念在类外进行该类的友元函数的定义,这样在它的类外也可以使用类中的私有成员。

    # define _CRT_SECURE_NO_WARNINGS 1
    #include<iostream>
    #include<windows.h>
    using namespace std;
    
    class Date
    {
    	friend void Display(const Date& d);
    	friend void operator<<(ostream& out, const Date& d);
    	friend void operator>>(istream& in, Date& d);
    	
    public:
    	Date(int year, int month, int day)
    	{
    		cout << "构造调用成功了" << endl;
    		_year = year;
    		_month = month;
    		_day = day;
    	}
    	// 拷贝构造函数
    	Date(const Date& d)
    	{
    		cout << "拷贝构造被调用了" << endl;
    		_year = d._year;
    		_month = d._month;
    		_day = d._day;
    	}
    	void operator<<(ostream& out)
    	{
    		out << _year << "_" << _month << "_" << _day << endl;
    	}
    private:
    	int _year;
    	int _month;
    	int _day;
    };
    void Display(const Date& d)
    {
    	cout << d._year << " " << d._month << " " << d._day << endl;
    }
    void operator<<(ostream& out,const Date& d)
    {
    	out << d._year << "_" << d._month << "_" << d._day << endl;
    }
    void operator>>(istream& in, Date& d)
    {
    	in >> d._year;
    	in >> d._month;
    	in >> d._day;
    }
    int main()
    {
    	Date d1(2017, 3, 6);
    	d1 << cout;  
    	//d1.operator<<(cout);等同于上式
    	//上面就是在类中定义的函数
    	cin >> d1;
    	cout << d1;
    	Display(d1);
    	//这个是在类外定义的友元函数
    	system("pause");
    	return 0;
    }


    
    看看运行的结果:
    
    
    
    
    
    
    
    
    
    
    


    友元函数的调用就是在类外实现完毕,在类内往它声明之前加一个friend关键字声明,这样他就是一个合格
    的友元函数,可以访问类内的所有成员,是不是很方便?

    还有!!

    我们刚刚发现在类中定义了一个运算符“<<”的重载,但是我们可以发现在类的内部调用他的方式略显
    别扭“d1<<cout”,所谓为了解决这个问题,我们在类外调用一个友元函数,这样就可以将参数的位置调换
    完美的解决了调用方式的问题,直接"cout<<d1",就可以直接使用。

    还有友元类的使用:

    整个类可以是另一个类的友元。友元类的每个成员函数都是另一个类的友元函数,都可访问另一个类中的保
    护或私有数据成员。

    class Time
    {
         // Date是Time 的友元,所以 Date可以访问Time的所有成员。
         friend class Date;
    private :
         int _hour ;
         int _minute ;
         int _second ;
    };
    
    class Date
    {
    public :
         void Display ()
        {
              cout<<"year:" <<_year<< endl;
              cout<<"month:" <<_month<< endl;
              cout<<"day:" <<_day<< endl;
    
              // 定义为友元类后,可以访问Time类对象的所有成员
              cout<<"hour:" <<_t. _hour<<endl ;
              cout<<"minute:" <<_t. _minute<<endl ;
              cout<<"second:" <<_t. _second<<endl <<endl;
        }
    
    private :
         int _year ;     // 年
         int _month ;    // 月
         int _day ;      // 日
    
         Time _t ;
    };
    
    void Test ()
    {
         Date d1 ;
         d1.Display ();
    }
    




    不出所料,这里可以访问友元类的私有成员。

    具体都是这样用的,但是呢友元一定程度上破坏了C++的封装,友元不宜多用,在恰当的地方使用友元。




    展开全文
  • 友元函数。 1.为什么C++不支持普通函数为虚函数? 普通函数(非成员函数)只能被overload,不能被override,声明为虚函数也没有什么意思,因此编译器会在编译时邦定函数。 2.为什么C++不支持构造函数为虚函数? 这...
  • 目录 友元到底是什么意思? 什么是友元函数? 什么是友元类?...友元到底是什么意思?...友元在我的理解中是“朋友之间互通有无的一种表现”,只要在类体中...首先,我要说的是“友元函数是个外部函数,它不是类的成...
  • 什么是友元函数

    2010-06-16 16:32:00
    友元函数用来访问类的非公有成员。友元函数不是类的成员函数。   <br />What is a friend function? A friend function is used for accessing the non-public members of a class.A friend ...
  • 友元函数和友元类是什么? 优缺点 应用
  • C++友元函数和友元类

    2020-02-13 08:10:52
    友元是什么: 友元不是成员函数,但是它可以访问类中的私有成员。 友元函数 通过friend关键字,我们可以将不属于当前类的一个函数在当前类中加以声明,该函数便可以成为当前类的友元函数。成员函数也可以是友元...
  • 友元函数,友元类

    2013-11-19 13:31:22
    1. 什么是友元函数?  一个类的私有数据成员通常只能由类的函数成员来访问,而友元函数可以访问类的私有数据成员,也能访问其保护成员 2. 友元函数的用处体现在哪里?  2.1 使用友元函数可提高性能,如:用友元...
  • 友元函数、友元类

    2013-10-09 11:26:55
    1. 什么是友元函数?  一个类的私有数据成员通常只能由类的函数成员来访问,而友元函数可以访问类的私有数据成员,也能访问其保护成员 2. 友元函数的用处体现在哪里?  2.1 使用友元函数可提高性能,如:用友元...
  • C++ 友元函数

    2018-05-13 16:55:01
    1、为什么要引入友元函数:在实现类之间数据共享时,减少系统开销,提高效率 允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数(友元函数不是类的成员函数,普通函数) 优点:能够...
  • 什么场景下会用到友元函数

    千次阅读 2017-10-11 07:56:42
    什么场景下会用到友元函数友元函数的作用是什么友元函数和普通成员函数又有怎样的区别?这都是C++当中的一些基本概念,掌握好了无论是维护项目还是做项目开发都大有裨益。本文主要浅谈一下C++中的友元函数,如有...
  • C++ 友元类和友元函数

    2020-04-28 17:09:46
    C++友元概述两个例子例1:友元类例2:友元函数 概述 C++友元C++独有的一种机制,为了解决访问类私有成员变量, 先提出一个问题:这样违反 类的封装性的,为什么还要有这种机制呢? 分为:友元类和友元函数 关键词...
  • 什么是友元? 友元就是朋友,c++中为了方便访问某个类的私有成员,引入了友元的概念 友元用 “friend” 定义 友元函数 友元函数分为两种 友元全局函数 友元成员函数 友元全局函数 class Coordinate { friend void...
  • c++ 友元函数 友元类

    2017-04-04 22:50:56
    什么会有友元函数?结合着类的特性和类中一般成员函数,我们可以这样理解:类具有封装和信息隐藏的特性。只有类的成员函数才能访问类的私有成员,程序中的其他函数是无法访问私有成员的。非成员函数可以访问类中的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 846
精华内容 338
关键字:

友元函数是什么