C++ 友元

咱们一起学C++第八十九篇:之C++友元机制深入剖析与嵌套友元 在C++学习的道路上,我们共同努力,不断深入理解这门语言的各种特性。此前,我们学习了友元机制的基本概念和作用,今天,我们将进一步深入探讨友元机制中的一些复杂情况,包括友元函数的声明顺序、传递对象地址与不完全类型说明的关系,以及嵌套友元的概念和使用规则。理解这些知识将有助于我们在更复杂的编程场景中正确运用友元机制,同时也能更好地理解C++语言在访问控制和数据封装方面的设计理念。 阅读详情

友元

友元 英文 friend。friend 翻译成中文就是朋友,翻译成术语就是:友元。朋友就很好理解了,我的钱你随便花,我的东西你随便用;当然我也是你的朋友,你的钱我随便花,你的东西我随便用。

当然在 C++ 里,类与类 之间可以作为友元,那么这个类就可以去操作另外一个类里面私有的成员;函数与函数 之间也可以作为 友元,所以友元分为: 友元函数 和 友元类。

我们通过一个例子一看就明白了:

写代码

#include <iostream>
#include <string>

using namespace std;

class Screen{
public:
    typedef std::string::size_type index;

    Screen(int ht=0, int wd=0):contents(ht*wd, ' '), cursor(0), height(ht), width(wd){}

    int area() const{
        return height * width;
    }
private:
    std::string contents; 
    index cursor;
    int height, width;
};



int main(){
    Screen a;
    cout << a.area() << endl;
    cout << "OK" << endl;

    return 0;
}

运行现在的程序,程序是可以正常使用的。

现在,我们在main() 函数的同一级,编写一个函数,这个函数的功能是:计算屏幕(Screen)的面积。

// 这个函数不是类的成员函数
int calcArea(Screen & screen){
    return screen.height * screen.width;
}

如果这个函数像上面这个样子编写,程序编译都通不过。因为 height 和 width 都是 Screen 类的私有成员。这两个私有的数据成员只能在类的内部使用,只能被类的内部函数使用,因为这个calcArea() 函数不是类内部的成员函数,所以它是不能使用类内部的私有成员的。
那么,假如现在,我们把这个 calcArea() 函数变成这个 Screen 类的友元,就是朋友,那么这个函数就可以使用类里面私有的成员了。就像是:你是我的朋友,到我家里来,就像到自己家里一样,随便吃随便用随便拿。

现在我们就来定义友元函数。我们将calcArea() 函数定义成友元函数。

在 Screen 类里面,public里面添加下面这句代码就可以。就这么简单:

    friend int calcArea(Screen & screen);

现在,我们在编译程序,就没有错误了。运行也没有问题。main() 函数里面写成下面这个样子,来测试:

int main(){
    Screen a;
    cout << a.area() << endl;
    cout << calcArea(a) << endl;
    cout << "OK" << endl;
    while(1){}
    return 0;
}

我们也可以将一个类编写成友元,我们现在来看下面这个例子:(注意: 要将下面的这段代码放到Screen类的下面,否则Window_Mgr类找不到 Screen类。)

// 窗口管理类 - 对Screen类进行管理
class Window_Mgr{
public:
    // 重定位 - 就是改变窗口的height 和 width
    void relocate(int r, int c, Screen& s){
        s.height += r;
        s.width + c;
    }
};

因为 Screen 类里的 height 和 width 是私有的,不能再 Window_Mgr 类里面使用的,除非它是友元。
现在编译程序是报错的。
我们现在可以将Window_Mgr类作为Screen类的友元。需要做的事情,只需要:在Screen类里面的public里面添加下面一句代码:

    friend class Window_Mgr;

现在,我们将Window_Mgr 这个整个类都作为 Screen类的友元,也就是说:它们现在是朋友,我们家里的人可以随便到你们家里面来,你们家里的人也可以随便到我们家里面来。

我们在 main() 函数里面测试一下:

int main(){
    Screen a(60, 100);
    cout << a.area() << endl;

    Window_Mgr w;
    w.relocate(10, 20, a);
    cout << calcArea(a) << endl;

    cout << "OK" << endl;
    while(1){}
    return 0;
}

这就是友元,懂了吗?


如果我们现在不行让这个 Window_Mgr类作为 Screen类的友元,而是希望只是 Window_Mgr类中的一个成员函数是Screen类的友元。要如何操作呢?

我们在定义一个类,Dog。Dog类里面就有很多的成员函数。

我现在不想将Dog类全部做成Screen类的友元,我只想将Dog类里面的foo()共有函数作为Screen类的友元,那现在我们要如何去做呢?
很简单,我们在Screen类的public里面添加下面这句代码就可以:

    friend int Dog::foo(Screen & );

Q: 现在程序编译时会通过的,这是为什么?


A: 有一个问题需要强调一下:友元定义 和 友元声明 之间有一个依赖。

如果我们将 Dog 类 放在 Screen 类的下面,那么 Dog 类是可以找到 Screen 类,但是 Screen 类却找不到 Dog 类里面的foo() 函数,因为我们在编写 foo() 函数的时候,是使用的声明和定义一体的形式编写的。
如果我们将 Dog 类 放在 Screen 类的上面, 那么 Screen 类是可以找到 Dog 类里面的 foo() 函数,但是 Dog 类现在又找不到 Screen 类了。所以,不管你将 Dog 类放在程序的什么位置,程序都是没有办法编译通过。要怎样解决这个问题呢?

我们需要在 Screen 类上面 这样写:

class Screen;

class Dog{
public:
    int foo(Screen & screen);

    int koo(Screen & screen){
        return 1;
    }
};

先对 Screen 类进行声明,接下定义 Dog 类。并且在 Dog 类里面 我们将 foo() 函数写成声明的形式。这样就没有使用到 Screen 类里面的成员,这样,程序在编译这段代码的时候不需要去找 Screen 的定义。


接着,我们在 Screen 类的下面 这样写:

int Dog::foo(Screen & screen){
    return  screen.height * screen.width;
}

我们在 Screen 类的下面都 Dog 类里面的成员函数 foo() 函数进行定义。这样做的原因是:因为 foo() 成员函数里面使用到了 Screen 类里面定义的成员变量,程序在编译这段函数的代码的时候,会去上向上找 Screen 类的定义,刚好我们将 foo() 函数的定义写在Screen 定义的下面,所以这样写就可以用个编译。

现在在main() 函数中写一些测试代码:

int main(){
    Screen a(60, 100);
    cout << a.area() << endl;

    Dog d;
    cout << d.foo(a) << endl;

    cout << "OK" << endl;
    while(1){}
    return 0;
}

现在 友元 我们就都介绍完毕了。

最后,完整的代码贴上:

#include <iostream>
#include <string>

using namespace std;

class Screen;

class Dog{
public:
    int foo(Screen & screen);

    int koo(Screen & screen){
        return 1;
    }
};


class Screen{
public:
    friend int calcArea(Screen & screen);
    friend class Window_Mgr;
    friend int Dog::foo(Screen & screen);

    typedef std::string::size_type index;

    Screen(int ht=0, int wd=0):contents(ht*wd, ' '), 
        cursor(0), height(ht), width(wd){}

    int area() const{
        return height * width;
    }

private:
    std::string contents; 
    index cursor;
    int height, width;
};

// 窗口管理类 - 对Screen类进行管理
class Window_Mgr{
public:
    // 重定位 - 就是改变窗口的height 和 width
    void relocate(int r, int c, Screen& s){
        s.height += r;
        s.width += c;
    }
};

int Dog::foo(Screen & screen){
    return  screen.height * screen.width;
}


// 这个函数不是类的成员函数
int calcArea(Screen & screen){
    return screen.height * screen.width;
}

int main(){
    Screen a(60, 100);
    cout << a.area() << endl;

    Window_Mgr w;
    w.relocate(10, 20, a);
    cout << calcArea(a) << endl;

    Dog d;
    cout << d.foo(a) << endl;

    cout << "OK" << endl;
    while(1){}
    return 0;
}


总结:
1 . 今天我们学习的就是友元,友元就是找朋友。我们可以将一个函数作为友元,我们也可以将一个类作为友元,也可以将类中的一个成员函数作为友元。
2 . 所有友元函数有两种: 普通函数 和 类的成员函数(共有 和 私有都可以。)
3 . 友元,道理上是很简单的。友元了之后,就可以操作所有私有的数据成员和私有函数。

C++ Friend 友元机制 友元函数(Friend Function)是一种定义在类外部的普通函数,但通过在类定义中用friend关键字声明,使其能够访问该类的所有成员,包括私有和保护成员。友元函数不是类的成员函数,在调用时不需要通过对象实例。// 私有成员public:// 声明普通函数 FriendFunc 为友元函数// 友元函数的定义(注意它不是类的成员函数)// 可以直接访问 MyClass 的私有成员友元类(Friend Class)是指一个类将另一个类声明为自己的友元。 阅读详情

相关推荐

horizon之为connection服务器配置证书

打开connection1服务器(connection2 同connection1)再输入connection1的IP地址 可通过域名和IP地址进行登录。这时候用域名登录就发现证书已经没有警告了。win+R 调出“运行”,输入mmc。connection2 同上。如果还有报错请重启一下服务器。打开connection1。可以把这个先删掉 没用。打开DC_01服务器。右键选择证书颁发机构。友好名称只能是vdm。重启之后就没有报错了。

送个祝福给小豪的博客 2960

C++友元详解

友元介绍

m0_73803550的博客 8081

Dify整合FireCrawl与百度搜索实战:手把手教你打造全能研究助手

本文手把手教你基于Dify平台,整合FireCrawl网页爬虫与百度搜索能力,构建一个能同时处理本地文档与实时网络信息的全能研究助手。通过部署核心环境、配置模型、接入两大工具并设计自动化工作流,实现从问题提出到深度分析报告生成的一站式解决方案,极大提升信息调研与整合效率。

weixin_29062963的博客 500

C++:友元(看这一篇就够了)

本文介绍了C++友元,包括为什么使用友元,怎样使用友元以及友元的三种实现

孙悟空 8万+

SpringCloud 2025王炸更新!GraalVM原生镜像启动速度提升90%实战

在当今云原生和Serverless架构盛行的时代,应用的启动速度已成为衡量技术栈竞争力的关键指标。传统SpringCloud应用由于依赖JVM的动态类加载、反射等机制,启动时间通常超过30秒,在Kubernetes滚动更新和函数计算场景下成为显著性能瓶颈。2025年,SpringCloud迎来里程碑式更新,通过深度集成GraalVM原生镜像技术,实现了启动速度提升90%的惊人突破,让SpringCloud应用正式进入"秒级启动"时代。

小筱在线博客 1098

Lumerical FDTD新手必看:从零开始搭建光子晶体仿真环境(附完整脚本)

本文为Lumerical FDTD新手提供光子晶体仿真环境的完整搭建指南,涵盖从基础参数设置到脚本编写的全流程。通过典型光子晶体带隙分析案例,详细讲解结构建模、仿真参数配置及后处理技巧,并附赠完整MATLAB脚本,帮助用户快速掌握FDTD仿真核心技术。

3c4x5z6v7b的博客 1050

C++——友元 & 内部类

1. 友元函数 友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字 举例: class Date { friend ostream& operator<<(ostream& _cout, const Date& d); friend istream& operator>>(istream& _cin, Date& d); public: Dat.

m0_46657980的博客 1275

【AUTOSAR-E2E】-2.1-配置E2E:基于E2EPW配置一个RX接收的Signal Group(使用E2E Profile 2)

《共13页精讲》:此法也适用于E2E Profile 4/5/6/7/11/22 目录 1 检查CAN Matrix Arxml/DBC是否满足E2E需求 2 在DaVinci Developer中为Port添加E2E保护 3 在DaVinci Configurator settings设置 4 如何使用应用层的E2E保护 5 结尾 <--返回「Autosar_BSW高阶配置」总目录--> <--返回「Autosar_BSW高阶配置」专栏主页--> <--

「汽车电子助手」的博客 4417

C++友元

C++友元函数;友元类

qq_63976098的博客 2050

YOLOv8融合HAttention:激活更多像素的注意力机制科研实践指南

HAttention通过层级化像素激活与融合的设计,为YOLOv8的像素级特征利用能力带来了质的飞跃。从原理理解到代码实现,再到集成调优,每一步都是科研中“解决像素信息遗漏难题”的具体实践。如果你在实验中发现某类细节或大尺度目标的检测仍有不足,可以尝试结合数据增强(如随机裁剪、多尺度训练)来强化模型对像素特征的学习能力。科研的价值在于不断挖掘技术的潜力,希望这份指南能真正帮你在目标检测的像素级特征利用领域找到新的突破点,祝你在科研探索中持续收获创新与成长。

FJN110的博客 105

S7-1200PLC与昆仑通态触摸屏以太网通信的具体方法和步骤(图文)

S7-1200PLC与昆仑通态触摸屏以太网通信的具体方法和步骤(图文)

Robot_PLC_HMI_Automation 1万+

【C++】友元--最全解析(友元是什么?我们应该如何理解友元?友元可以应用在那些场景?)

在C++编程语言中,友元函数(Friend Function)是一种特殊的函数,具有访问类中私有成员和保护成员的权限,尽管它不是类的成员函数。友元函数的存在使得类的设计更加灵活,能够在需要时授予外部函数访问类的私有成员的能力。本文将详细介绍C++中的友元函数,包括其定义、使用场景、优缺点以及示例。

weixin_45031801的博客 5574

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

C++ 友元类

1.在C++中,我们使用类对数据进行了隐藏和封装,类的数据成员一般都定义为私有成员,成员函数一般都定义为公有的,以此提供类与外界的通讯接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该函数的友元函数。除了友元函数外,还有友元类,两者统称为友元。友元的作用是提高了程序的运行效率(即减少了类型检查和安全性检查等都需要时间开销),但它破坏了类的封装性和隐藏性,使得非成员函数可以访问类的私有成员。 2.友元类 : 友元类的所有成员函数都是另一个类的友

weixin_43107240的博客 4万+

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++中的友元

C++中的友元友元的概念引入友元的分类类的非成员函数友元类的成员函数友元类友元友元的特点友元说明 友元的概念引入 C++的最重要的特点之一就是封装性和继承性。对于类的封装性来说,就是类的私有成员和保护成员只能在设计类时它所定义的函数内使用,即私有成员和保护成员只能通过该类的成员函数来访问。 当我们需要在类的外部访问该类的私有成员和保护成员时,就可以利用友元(**friend**)来实现这一操作。 友元的分类 类的非成员函数友元 类的非成员函数友元: 表示友元函数不是当前类的成员函数,而是独立于当前类

qq_44423388的博客 550

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

C++ 友元

C++ 友元1. 何为友元2. 同类对象之间无隐私3.异类对象之间有友元3.1 友元函数3.1.1 全局函数作友元函数3.1.2 类成员函数作友元函数3.2 友元类4. 小结4.1 声明位置4.2 友元利弊4.3 注意事项 1. 何为友元 采用类的机制后实现了数据的隐藏与封装,类的数据成员一般定义为私有成员,成员函数一般定义为公有的,依此提供类与外界间的通信接口。但是,有时需要定义一些函数,这些函数不是类的一部分,但又需要频繁地访问类的数据成员,这时可以将这些函数定义为该类的友元函数。除了友元函数外,还有友

qq_43414070的博客 1590

C++ 友元机制

在 C++ 编程世界中,友元机制是一项独特且强大的功能,它赋予了特定函数或类访问其他类私有成员的权限,突破了常规的访问限制。使用不当,则会给代码带来一系列隐患。例如,在实现游戏引擎的 3D 渲染时,允许 Matrix 类直接访问 Vector 的私有数据(数学计算优化)属于合理使用;日常开发应优先使用常规工具(公共接口),只有遇到必须突破封装的情况时才谨慎使用友元,并做好安全防护。要记住,每增加一个友元,就是给系统增加一个潜在入口,必须如履薄冰地管理。通用的业务系统,追求稳定性和通用性,如公共图书馆系统。

2401_84228999的博客 1857

10 C++ 友元

C++友元机制摘要 友元(friend)允许外部函数或类访问当前类的私有和保护成员,主要分为友元函数、友元类和友元成员函数三种类型。关键特性包括: 单向非传递:友元关系不可逆且不传递 灵活声明:可在类任意位置声明,不受访问控制符限制 典型应用:运算符重载(如<<)、跨类数据共享、单元测试 优势在于提供高效访问和自然语法,但会破坏封装性。建议优先使用成员函数,仅在必要场景(如流操作符重载)使用友元,并严格限制友元范围。 示例场景:设备控制器(友元类)访问设备温度数据(私有成员)

17208955的博客 1680

C++友元类

友元类 不仅可以将一个函数声明为一个类的“朋友”,还可以将一个类(例如 B类)声明为另一个类(例如 A类)的“朋友”。这时B类就是A类的友元类。友元类B中的所有函数都是A类的友元函数,可以访问A类中的所有成员。 声明友元类的一般形式为: friend class 类名; 所以,可以在A类的定义体中,可以使用如下语句声明B类为其友元类: friend class B; 那么,类B是类A的友元类。所以,类B的成员函数就可以访问类A的私有成员。 ...

LC的专栏 7397

C++ 中的友元

关于友元关系:在C++中,友元(Friend)功能是一个相对特殊的概念,允许某些特定的函数或其他类访问当前类的私有(private)或受保护(protected)成员。友元功能是C++中用于特定情况下实现类之间数据访问的机制。优点:打破类的封装,广泛应用于操作符重载缺点:破坏了类的封装,类之间互相依赖,代码高度耦合,头文件,类声明,粉墨登场,没有固定设计模式,难以设计友元的4种主要类型:1 友元函数:友元函数可以是任何普通函数。它被允许访问某个类的所有成员(包括私有和受保护)。

抟土成人祖,炼石补青天。眼中览银河,手可摘星辰。 500

c++类——友元

如有兴趣了解更多请关注我的个人博客。

xiaohei07的博客 2138
上一篇: 安装 SQL Server 2014 Express
下一篇: Auto Control 001 自动控制原理 自动控制的一般概念
AoboSir
博客等级 码龄10年 996粉丝 285原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值