文档章节

C++ 友元函数用法总结

清风伴月
 清风伴月
发布于 2017/05/05 13:57
字数 1260
阅读 16
收藏 0

C++ friend 用法总结

C++中的友元机制允许类的非公有成员被一个类或者函数访问,友元按类型分为三种:

普通非类成员函数作为友元、类的成员函数作为友元、类作为友元。

1、友元的内容

友元包括友元的声明以及友元的定义。友元的声明默认为了extern,就是说友元类或者友元函数的作用域已经扩展到了包含该类定义的作用域,所以即便我们在类的内部定义友元函数也是没有关系的。

2、普通的非成员函数友元

这类友元函数通常是操作符,例如输入输出操作符.示例如下所示:

//OpeClass.h  
#pragma once  
class OpeClass  
{  
    friend int func(const OpeClass xx);  
public:  
    OpeClass(void);  
    OpeClass(int x,int y);  
    ~OpeClass(void);  
private:  
    int width;  
    int height;  
};  
//OpeClass.cpp  
#include "OpeClass.h"  
  
  
OpeClass::OpeClass(void)  
{  
    width = 50;  
    height = 50;  
}  
  
  
OpeClass::OpeClass(int x,int y):width(x),height(y)  
{  
}  
  
  
OpeClass::~OpeClass(void)  
{  
}  
  
  
int func(const OpeClass xx)  
{  
    return xx.height * xx.width;  
} 
//main.cpp  
#include "OpeClass.h"  
#include <iostream>  
using namespace std;  
  
  
void main()  
{  
    OpeClass XO;  
    cout<<func(XO);  
    system("pause");  
}  

3、类作为友元

类作为友元需要注意的是友元类和原始类之间的相互依赖关系,如果在友元类中定义的函数使用到了原始类的私有变量,那么就需要在友元类定义的文件中包含原始类定义的头文件。
但是在原始类的定义中(包含友元类声明的那个类),就不需要包含友元类的头文件,也不需要在类定义前去声明友元类,因为友元类的声明自身就是一种声明(它指明可以在类外找到友元类),示例程序如下所示:

//A.h  
#pragma once  
#include <iostream>  
using namespace std;  
class A  
{  
    friend class B;  
public:  
    ~A(void);  
    static void func()  
    {  
        cout<<"This is in A"<<endl;  
    }  
private:  
    A(){};  
    static const A Test;  
}; 
    //A.cpp  
    #include "A.h"  
    const A A::Test = A();  
    A::~A(void)  
    {  
    }  
//B.h  
#pragma once  
#include "C.h"  
class B  
{  
public:  
    B(void);  
    ~B(void);  
    void func(C& c);  
}; 
    //B.cpp  
    #include "B.h"  
    #include "A.h"  
    #include "C.h"  
    #include <iostream>  
    using namespace std;  
      
      
    B::B(void)  
    {  
    }  
      
      
      
      
    B::~B(void)  
    {  
    }  
      
      
    void B::func(C& c)  
    {  
        cout<<"This is in B"<<endl;  
        A::Test.func();  
        c.func(A::Test);  
    }  
    //C.h  
    #pragma once  
    class A;  
    class C  
    {  
    public:  
        C(void);  
        ~C(void);  
        void func(const A& a);  
    };  
//C.cpp  
#include "C.h"  
#include <iostream>  
using namespace std;  
  
C::C(void)  
{  
}  
  
C::~C(void)  
{  
}  
  
void C::func(const A& a)  
{  
    cout<<"This is in C"<<endl;  
} 
    //main.cpp  
    #include "A.h"  
    #include "B.h"  
    #include "C.h"  
    #include <iostream>  
    using namespace std;  
      
    void main()  
    {  
        B b;  
        C c;  
        b.func(c);  
        system("pause");  
    }  

 

4、类成员函数作为友元函数

这个稍微有点复杂,因为你要类成员函数作为友元,你在声明友元的时候要用类限定符,所以必须先定义包含友元函数的类,但是在定义友元的函数时候,又必须事先定义原始类。通常的做法先定义包含友元函数的类,再定义原始类,这个顺序不能乱。(如果是友元类,则没有这种这种必须)如下面所示:

    //B.h  
    #pragma once  
    class A;  
    class B  
    {  
    public:  
        B(void);  
        ~B(void);  
        int func(A xx);  
    };  
    //A.h  
    #pragma once  
    #include "B.h"  
    class A  
    {  
    friend int B::func(A xx);  
    public:  
        A(void):mx(20),my(30){}  
        ~A(void){}  
    private:  
        int mx;  
        int my;  
    };  
    //B.cpp  
    #include "B.h"  
    #include "A.h"  
      
      
    B::B(void)  
    {  
    }  
      
      
    B::~B(void)  
    {  
    }  
      
    int B::func(A xx)  
    {  
        return xx.mx * xx.my;  
    }  
    //main.cpp  
    #include "A.h"  
    #include "B.h"  
    #include <iostream>  
    using namespace std;  
    void main()  
    {  
        A a;  
        B b;  
        cout<<b.func(a)<<endl;  
        system("pause");  
    }  

 

5、友元不具有相互性,只具有单项性

若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。

6、友元不能被继承

B是A的友元类,C是B的子类,推不出C是A的友元

7、友元不具有传递性

B是A的友元,C是B的友元,推不出C是A的友元

8、相互为友元的类

这个其实没什么好注意的,下面是实例,类A,类B互为友元

    //A.h  
    #pragma once  
    class A  
    {  
    friend class B;  
    public:  
        A(void);  
        ~A(void);  
        int funa(B& b);  
    private:  
        int mx;  
        int my;  
    };  
    //A.cpp  
    #include "A.h"  
    #include "B.h"  
      
      
    A::A(void)  
    {  
        mx = 10;  
        my = 10;  
    }  
      
      
    A::~A(void)  
    {  
    }  
      
      
    int A::funa(B& b)  
    {  
        return b.mb * b.mc;  
    }  
    //B.h  
    #pragma once  
    class B  
    {  
        friend class A;  
    public:  
        B(void);  
        ~B(void);  
        int funb(A& a);  
    private:  
        int mb;  
        int mc;  
    };  
    //B.cpp  
    #include "B.h"  
    #include "A.h"  
      
      
    B::B(void)  
    {  
        mb = 20;  
        mc = 20;  
    }  
      
    B::~B(void)  
    {  
    }  
      
    int B::funb(A& a)  
    {  
        return a.mx *a.my;  
    }  
//main.cpp  
#include "A.h"  
#include "B.h"  
#include <iostream>  
using namespace std;  
void main()  
{  
    A a;  
    B b;  
    cout<<a.funa(b)<<endl;  
    cout<<b.funb(a)<<endl;  
    system("pause");  
} 

 

9、如果想要指定两个类都有成员函数作为对方的友元,那么必须第2个类是第一个类的友元

    //A.h  
    #pragma once  
      
    // class B is a friend class of A  
    class A  
    {  
        friend class B;  
    public:  
        A(void):ma(10),mb(20){}  
        ~A(void){}  
        int funa(B& b);  
    private:  
        int ma;  
        int mb;  
    };  
    //B.h  
    #pragma once  
    #include "A.h"  
      
      
    // A's function funa is a friend function of B  
    class B  
    {  
        friend int A::funa(B& b);  
    public:  
        B(void);  
        ~B(void);  
        int funb(A& a);  
        int func(A& a);  
    private:  
        int mx;  
        int my;  
    };  
    //A.cpp  
    #include "A.h"  
    #include "B.h"  
      
      
    int A::funa(B& b)  
    {  
        return  b.mx * b.my;  
    }  
    //B.cpp  
    #include "B.h"  
      
    B::B(void):mx(12),my(15)  
    {  
    }  
      
      
    B::~B(void)  
    {  
    }  
      
      
    int B::funb(A& a)  
    {  
        return a.ma + a.mb;  
    }  
      
    int B::func(A& a)  
    {  
        return a.ma * a.mb;  
    }  
    //main.cpp  
    #include "A.h"  
    #include "B.h"  
    #include <iostream>  
    using namespace std;  
    void main()  
    {  
        A a;  
        B b;  
        cout<<a.funa(b)<<endl;  
        cout<<b.funb(a)<<endl;  
        cout<<b.func(a)<<endl;  
    }  

 

© 著作权归作者所有

清风伴月
粉丝 1
博文 129
码字总数 255659
作品 0
海淀
程序员
私信 提问
C++技巧之operator操作符

C++有时它的确是个耐玩的东东。operator它有两种用法,一种是operator overloading(操作符重载),一种是operator casting(操作隐式转换)。 1.operator overloading C++可以通过operator ...

Start-up
2012/10/29
0
0
C++友元函数和友元类(C++ friend)详解

私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行。这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书...

shzwork
04/21
0
0
C++类或结构作为map的key值

1.只有重载<的类或者结构才能作为map的key值。 string可以作为key值是因为string重载了< 2.如果不重载<会提示如下错误: error C2676: 二进制“<”: “const C”不定义该运算符或到预定义运算...

涩女郎
2015/08/20
0
0
SWIG入门5: C/C++初级特性3

1 函数重载 函数重载这个特性是C++对于C的一个最重要的扩充属性了。对于C语言来说,不可能有两个SYMBOL的名字是相同的,但C++语言为了实现函数重载的这个特性,讲函数的SYMBOL名改成了 ‘函数...

costaxu
2012/08/26
0
0
使用友元函数计算两点间的距离

//5_6.cpp 使用友元函数计算两点间的距离 //友元函数是类中用关键字friend修饰的非成员函数 #include #include // cmath是c++标准风格的头文件,位于std命名空间,用法和math.h差不多,都是包...

技术小美
2017/11/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【AI实战】手把手教你深度学习文字识别(文字检测篇:基于MSER, CTPN, SegLink, EAST等方法)

文字检测是文字识别过程中的一个非常重要的环节,文字检测的主要目标是将图片中的文字区域位置检测出来,以便于进行后面的文字识别,只有找到了文本所在区域,才能对其内容进行识别。 文字检...

雪饼
37分钟前
1
0
思维导图XMind 8 Pro 绿化方法(附序列号)

按部就班: Step 1 -全新下载最新版本的 Xmind 8(注必须是英文官方的版本,中文代{过}{滤}理网站的版本修改过,无法使用pj); Step 2 -安装完毕后,点击文末的下载按钮下载pj补丁文件包,将...

一只小青蛙
今天
6
0
数据结构(ER数据库)设计规范

表命名规范 表命名的规则分为3个层级,层级之间通过_分割,例如b_r_identity、d_l_identity。规约为: [leavel]_[type]_[name] [leavel] 表示数据库表的层级和功能,分为: s:业务无关的系统...

随风溜达的向日葵
今天
5
0
阿里Sentinel控制台源码修改-对接Apollo规则持久化

https://github.com/alibaba/Sentinel/wiki/%E5%9C%A8%E7%94%9F%E4%BA%A7%E7%8E%AF%E5%A2%83%E4%B8%AD%E4%BD%BF%E7%94%A8-Sentinel 动态规则扩展 https://github.com/alibaba/Sentinel/wiki......

jxlgzwh
昨天
4
0
在Linux系统中创建SSH服务器别名

如果你经常通过 SSH 访问许多不同的远程系统,这个技巧将为你节省一些时间。你可以通过 SSH 为频繁访问的系统创建 SSH 别名,这样你就不必记住所有不同的用户名、主机名、SSH 端口号和 IP 地...

老孟的Linux私房菜
昨天
11
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部