zoukankan      html  css  js  c++  java
  • C++中的友元函数的总结

    1为什么要使用友元函数
    在实现类之间数据共享时,减少系统开销,提高效率。如果类A中的函数要访问类B中的成员(例如:智能指针类的实现),那么类A中该函数要是类B的友元函数。具体说:为了
    使其他类的成员函数直接访问该类的私有变量。即:允许外面的类或函数去访问类的私有变量和保护变量,从而使两个类共享同一函数。
    实际上具体大概有下面两种情况需要使用友元函数:(1)运算符重载的某些场合需要使用友元。(2)两个类要共享数据的时候。

    使用友元函数的优缺点
    优点:能够提高效率,表达简单、清晰。
    缺点:友元函数破环了封装机制,尽量不使用成员函数,除非不得已的情况下才使用友元函数。

    2.友元函数的使用

    友元函数的参数:
    因为友元函数没有this指针,则参数要有三种情况:
    要访问非static成员时,需要对象做参数
     要访问static成员或全局变量时,则不需要对象做参数;
    如果做参数的对象是全局对象,则不需要对象做参数;

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

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

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


    普通函数友元函数

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

    语法:
    声明: friend + 普通函数声明
    实现位置:可以在类外或类中
    实现代码:与普通函数相同
    调用:类似普通函数,直接调用

    代码:

    class Interger
    {
    	friend void Print(const INTEGER& obj);//声明友元函数
    };
    void Print(const INTEGER& obj)
    {
    	//函数体
    }
    void main()
    {
    	Interger obj;
    	Print(obj);//直接调用
    }
    

      

    类Y的所有成员函数都为类X友元函数—友元类
    目的:使用单个声明使Y类的所有函数成为类X的友元,它提供一种类之间合作的一种方式,使类Y的对象可以具有类X和类Y的功能。
    语法:
    声明位置:公有私有均可,常写为私有(把类看成一个变量)
    声明: friend + 类名(不是对象哦)
    代码:

    class girl;
    class boy
    {
    public:
    	void disp(girl &);
    };
    void boy::disp(girl &x) //函数disp()为类boy的成员函数,也是类girl的友元函数
    {
    	cout<<"girl's name is:"<<x.name<<",age:"<<x.age<<endl;//借助友元,在boy的成员函数disp中,借助girl的对象,直接访问girl的私有变量
    }
    class girl
    {
    private:
      char *name;
      int age;
      friend boy; //声明类boy是类girl的友元
    };
    

      

    类Y的一个成员函数为类X的友元函数
    目的:使类Y的一个成员函数成为类X的友元,具体而言:在类Y的这个成员函数中,借助参数X,可以直接以X的私有变量
    语法:
    声明位置:声明在公有中 (本身为函数)
    声明:friend + 成员函数的声明
    调用:先定义Y的对象y---使用y调用自己的成员函数---自己的成员函数中使用了友元机制
    代码:
    实现代码和上一代码中的实现及其相似只是设置友元的时候变为friend void boy::disp(girl &);

    小结:其实一些操作符的重载实现也是要在类外实现的,那么通常这样的话,声明为类的友元是必须滴。

    友元函数和类的成员函数的区别
    成员函数有this指针,而友元函数没有this指针。
    友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友。

    友元函数
    代码:

    ///
     /// @file    friendfunc.cc
     /// @author  Burgess Fan(1406832037@qq.com)
     /// @date    2016-06-20 20:38:18
     ///
    
    #include <iostream>
    using namespace std;
    class SalesData{
        friend void PrintInfo(SalesData &sdata);
    public:
        SalesData(const char*s,unsigned int n,double p)
        :BookNum(s)
        ,SaleNum(n)
        ,BookPrice(p)
        {
            cout<<"SalesData()"<<endl;
        }
        ~SalesData()
        {
            cout<<"~SalesData"<<endl;
        }
    private:
        const char* BookNum;
        unsigned int SaleNum;
        double BookPrice;
    };
    void PrintInfo(SalesData &sdata){
        cout<<"BookNum is:"<<sdata.BookNum<<endl;
        cout<<"SaleNum is:"<<sdata.SaleNum<<endl;
        cout<<"BookPrice is:"<<sdata.BookPrice<<endl;
    }
    int main(void){
        SalesData s("2016006",10,20.5);
        PrintInfo(s);
    
    
        return 0;
    }
    

      

  • 相关阅读:
    php性能测试工具
    linux的openssl
    Nginx与Apache的Rewrite规则的区别
    mysql索引总结----mysql 索引类型以及创建
    不支持正在使用的 .Net 组帧模式。有关详细信息,请参阅服务器日志--解决方案
    c#获取网页源代码
    关于线程间操作无效: 从不是创建控件“xx”的线程访问它,错误解决方法(自定义委托和系统委托Action或Func解决)
    联想笔记本官网驱动下载
    easy ui combotree的操作
    c# 搜狗拼音输入法,刷输入速度和累计输入
  • 原文地址:https://www.cnblogs.com/Burgess-Fan/p/7050142.html
Copyright © 2011-2022 走看看