C++中的friend class 用法总结


对于一个没有定义public访问权限的类,能够让其他的类操作它的私有成员往往是有用的。例如你写了一段binary tree的代码,Node是节点类,如果能够让连接多个节点的函数不需要调用public方法就能够访问到Node的私有成员的话,一定是很方便的。

Friend Classes(友元类)

C++中的friend关键字其实做这样的事情:在一个类中指明其他的类(或者)函数能够直接访问该类中的private和protected成员。
你可以这样来指明:

friend class aClass;

注意:friend在类中的声明可以再public、protected和private的如何一个控制域中,而不影响其效果。例如,如果你在protected域中有这样的声明,那么aClass类同样可以访问该类的private成员。
这有一个例子:

class Node   
{  
    private:   
       int data;  
       int key;  
       // ...  
  
    friend class BinaryTree; // class BinaryTree can now access data directly  
};  

这样BinaryTree就可以直接访问Node中的private的成员了,就像下面这样:

class BinaryTree  
{  
    private:  
       Node *root;  
  
    int find(int key);  
};  
int BinaryTree::find(int key)  
{  
    // check root for NULL...  
    if(root->key == key)  
    {  
        // no need to go through an accessor function  
        return root->data;  
    }  
    // perform rest of find  
}  

Friend Functions(友元函数)

友元函数和友元类的作用是一样的,它允许一个函数不需要通过其public接口就能够访问到类中的private和protected成员变量。
你可以这样去声明:

friend return_type class_name::function(args);

这里有一个例子:

class Node 
{
    private: 
       int data;
       int key;
       // ...

    friend int BinaryTree::find(); // Only BinaryTree's find function has access
};

这样find方法就可以直接访问Node中的私有成员变量了,而BinaryTree中的其他的方法去不能够直接的访问Node的成员变量。(这就是友元类和友元函数的区别)

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;  
}  

转载自https://blog.csdn.net/ddupd/article/details/38053159

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值