详解C++ friend关键字

概述:

1. 为什么要使用友元?

通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为 public( 共用的) ,然而这做带来的问题遍是任何外部函数都可以毫无约束的访问它操作它;另一种方法是利用 C++ 的 friend 修饰符,可以让一些你设定的函数能够对这些私有或保护数据进行操作。
2. 使用友元有哪些缺点?

使用友元的同时也破坏了类的封装特性,这即是友元最大的缺点。当对外声明为友元后,你的所有细节全部都暴露给了对方。
就好像你告诉你朋友你很有钱这个密秘,进而又把你有多少钱,多少古董,多少家产,多少小妾等等所有的家底全给他说了。
3. 友元怎样理解?

定一个友元函数,或是友元类,就是告诉对方:我的所有元素对你是开放的。这种 friend 是建立在灰常灰常灰常信任对方的基础上的。

一. 普通函数做为类的一个友元函数

在类里声明一个普通函数,在 前面加上 friend 修饰,那么这个函数就成了该类的友元。
这时这个普通函数可以访问该类的一切成员。
代码如下:

#include <iostream >    
using  namespace  std;  
 
class  MyClass
{
public :    
    MyClass(string name)    
    {    
        m_name = name;
    }
 
    //声明一个友元函数
    friend  void  Display(MyClass &mycalss);
 
Protected:
    string  m_name;
};
 
//定义这个友元函数
//写成 void MyClass::Display(MyClass &mycalss)  
void  Display(MyClass &mycalss)
{  
    cout << "Access Protected data : "<< mycalss.m_name << endl;  
}  
 
//测试
int main(int argc,char* argv[])
{
    MyClass test("Class A");  
    
    Display(test);
 
    return 0;
}
说明:
1. 声明这个友元函数可以在任何地方,可以在 public、protected 当然也可以在 privated 里。

2. 在这个友元函数里,你可以访问这个类里的所有的成员,所有的成员函数,而不管它是不是 public、protected 或 privated 的。
3. 定义友元函数时,不能写成 void MyClass::Display(MyClass &mycalss) 这点要注意。
二. 一个普通函数可以是多个类的友元函数

在每个类里面都有一个友元函数的声明,声明可以有多个,但定义只能有一个。
代码如下:
#include <iostream >    
using  namespace  std;
 
class MyClass_B;
 
class MyClass_A
{
public:    
    MyClass_A(string name)    
    {    
        m_name = name;
    }
 
    //声明一个友元函数
    friend void Display(MyClass_A &myA, MyClass_B &myB);
 
private:
    string m_name;
};
 
 
class MyClass_B
{
public:    
    MyClass_B(string name)    
    {    
        m_name = name;
    }
    
    //注意,又声明一个友元函数
    friend void Display(MyClass_A &myA, MyClass_B &myB);
    
private:
    string m_name;
};
 
//定义这个友元函数
void  Display(MyClass_A &myA, MyClass_B &myB)
{
    cout << "MyClass A : "<< myA.m_name << endl;
    cout << "MyClass B : "<< myB.m_name << endl;
}
 
//测试代码
int main(int argc,char* argv[])
{
    MyClass_A testA("Class A");  
    MyClass_B testB("Class A");  
    
    Display(testA, testB);
 
    return 0;
}
同样的,这个友元函数,可以访问这两个类的所有元素。

三. 一个类的成员函数也可以是另一个类的友元

从而可以使得一个类的成员函数可以操作另一个类的数据成员
#include <iostream >    
using  namespace  std;  
 
class MyClass_B;
 
//A 类
class MyClass_A
{
public:    
    MyClass_A(string name)    
    {    
        m_name = name;
    }
 
    void Function(MyClass_B &myB);
 
private:
    string m_name;
};
 
//B 类
class MyClass_B
{
public:    
    MyClass_B(string name)
    {
        m_name = name;
    }
    
    //友元函数声明,注意和普通函数的区别
    friend void MyClass_A::Function(MyClass_B &myB);
    
private:
    string m_name;
};
 
//函数定义
void MyClass_A::Function(MyClass_B &myB)
{
    cout<<myB.m_name<<endl;
}
 
//测试代码
int main(int argc,char* argv[])
{
    MyClass_A testA("Class A");  
    MyClass_B testB("Class B");  
    
    testA.Function(testB);
 
    return 0;
}
我们可以看到,B 类,对 A 类其中的一个函数开放,其结果是这个函数可以访问 B 类的所有元素。

四. 整个类也可以是另一个类的友元

友类的每个成员函数都可以访问另一个类的所有成员。

示例代码如下:

#include <iostream >    
using  namespace  std;  
 
//类 A
class MyClass_B;
 
class MyClass_A
{
public:    
    MyClass_A(string name)    
    {    
        m_name = name;
    }
 
    //友元类声明
    friend class MyClass_B;
 
private:
    string m_name;
};
 
//类 B
class MyClass_B
{
public:    
    MyClass_B(string name)
    {
        m_name = name;
    }
    
    void Display(MyClass_A &myA);
    
private:
    string m_name;
};
 
//成员函数
void MyClass_B::Display(MyClass_A &myA)
{  
    cout<<myA.m_name<<endl; //访问A的私有成员
 
    MyClass_A test("test");
 
    cout<<test.m_name<<endl; //好像A的所有元素在B里都存在一样
}
 
//测试代码
int main(int argc,char* argv[])
{
    MyClass_A testA("Class A");  
    MyClass_B testB("Class B");  
    
    testB.Display(testA);
 
    return 0;
}
此时B可以访问A的所有元素,就好像A在B里面一样。

五. 总结

简单的说就是:声明一个友元函数或者是友元类,就是要把自己完全暴露给对方。
————————————————
版权声明:本文为CSDN博主「lwbeyond」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lwbeyond/article/details/7591415

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值