详解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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
extern关键字在C语言中有多种用法。 第一种用法是在变量的声明中使用extern关键字,表示该变量在其他源文件中定义。例如,extern const char Buffer[];表示Buffer变量在其他文件中定义,并可以在当前文件中使用。 第二种用法是在函数的声明中使用extern关键字,表示该函数可能在其他源文件中定义。例如,extern int f();表示f函数可能在其他文件中定义,并可以在当前文件中使用。 第三种用法是在C++中使用extern "C"来指定函数的链接方式。这是为了解决C++函数重载带来的函数名和参数不同导致链接错误的问题。通过extern "C"修饰函数,告诉编译器保持函数名称不变,不生成用于链接的中间函数名。这通常在C++代码中与C函数交互时使用。 总而言之,extern关键字在C语言中用于声明变量和函数的链接方式,以及在C++中用于修饰函数以保持函数名称不变。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++全局变量的定义和声明](https://blog.csdn.net/webzhuce/article/details/38899635)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [C/C++种extern关键字详解](https://blog.csdn.net/weixin_38218095/article/details/96473556)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值