news 2026/10/20 20:31:29

# 友元#

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
# 友元#

友元定义:友元是C++中的一种机制,允许特定的函数或类访问另一个类的私有成员和保护成员;

友元

就是 「给外部对象 / 函数开绿灯」—— 允许指定的外部函数、外部类,直接访问当前类的private(私有)和protected(保护)成员,无需通过public接口,是对类封装性的灵活补充(而非破坏)。

友元主要分为

「友元函数」 全局函数作为类的友元;

语法格式:
class类名{
friend返回值类型函数名(形参);/声明友元函数
}:

友元函数可以访问所有私有成员和保护成员,一般情况下不去使用,使用不当会破坏程序面向对象的特性

友元函数不是成员函数,它定义在类的外部,只需要在类中

「友元成员函数」

语法格式:
class A
friend返回类型类名1:成员函数(类名2&);
/声明友元成员函数
}

一个类的成员函数作为另一个类的友元;

「友元类」

语法格式:
class类名1{
friend class类名2;/声明友元类

一个类作为另一个类的友元;

友元不具有相互性,若类B是类A的友元,类A不一定是类B的友元
友元不能被继承一你爹的朋友不一—定是你的朋友
友元不具有传递性一你朋友的朋友不一定是你的朋友

四、友元的核心特性与关键注意点
1.友元关系是单向的:
若House声明BestFriend为友元,BestFriend可访问House的私有成员,但House不能访问BestFriend的私有成员(除非BestFriend也声明House为友元)
2.友元关系不可传递:
若A是B的友元,B是c的友元,不能推出A是C的友元(好友的好友,不一定是你的好友)。
3.友元关系不可继承:
父类的友元,不会自动成为子类的友元;子类若想让其访问私有成员,需单独声明。
4.友元不破坏封装性(合理使用下):
友元是「按需开放权限」,而非全盘公开,适用于特定场景(如运算符重载、两个类紧密协作),避免为了访问私有成员而写大量冗余的getter/setter。

友元函数

#include <iostream> // 包含C++标准输入输出流头文件,用于cout等输出操作 using namespace std; // 使用标准命名空间,避免在代码中重复使用std::前缀 // 定义Box类 class Box { public: // 公共成员区域,外部可访问 Box(int w); // 声明构造函数,接收一个int类型参数用于初始化width friend void printfBoxWidth(Box box); // 声明友元函数,该函数可以访问Box类的私有成员 private: // 私有成员区域,仅类内部和友元可访问 int width; // 私有成员变量,存储盒子的宽度 }; // 实现Box类的构造函数 // 注意:这里使用双冒号::表示属于Box类的成员函数 Box::Box(int w) { width = w; // 将参数w的值赋给私有成员变量width // 更优写法:使用初始化列表 Box::Box(int w) : width(w) {} } // 实现友元函数printfBoxWidth // 友元函数不是类的成员函数,但可以访问类的私有成员 void printfBoxWidth(Box box) { // 输出Box对象的width值,由于是友元函数,可以直接访问私有成员 cout << "box width is " << box.width << endl; } // 主函数,程序入口点 int main() { Box b(10); // 创建Box类的对象b,调用构造函数将width初始化为10 // b.width; // 错误!width是私有成员,外部无法直接访问 printfBoxWidth(b); // 通过友元函数访问Box对象的私有成员width return 0; // 程序正常结束,返回0 }
#include <iostream> using namespace std; class B; // 自定义类 MyClass class MyClass { friend class B; // B类是MyClass类的友元类 public: int pub_a; static int pub_s; // 静态成员变量只能类内声明类外实现 //B目前不是一个完整的类,所以我们需要进行类内声明类外进行实现 void pub_print(B& obj); private: int pri_a; static int pri_s; protected: int pro_a; static int pro_s; }; // 静态成员变量只能类外实现 int MyClass::pub_s = 10; int MyClass::pri_s = 20; int MyClass::pro_s = 30; class B { //友元关系是一个单向的 //将MyClass类作为B类的友元类 friend class MyClass; public: // 访问MyClass类中的成员 void print() { // 访问MyClass类中的静态成员变量 // 直接访问MyClass类中的静态成员变量 cout << "pub_s = " << MyClass::pub_s << endl; cout << "pri_s = " << MyClass::pri_s << endl; cout << "pro_s = " << MyClass::pro_s << endl; } // 访问MyClass类中的非静态成员变量 //就需要给成员函数一个类 类型的形参 void print1(MyClass& obj) { obj.pub_a = 111; obj.pri_a = 222; obj.pro_a = 333; cout << "pub_a = " << obj.pub_a << endl; cout << "pri_a = " << obj.pri_a << endl; cout << "pro_a = " << obj.pro_a << endl; } protected: int pro_data; //非静态成员变量 }; void MyClass::pub_print(B& obj){ obj.pro_data = 100; cout << "pro_data=" << obj.pro_data << endl; } int main() { // 进行实例化对象 MyClass obj; B demo; demo.print(); demo.print1(obj); obj.pub_print(demo); return 0; }
#include <iostream> using namespace std; //自定义类 MyClass class MyClass{ friend void print(); //友元函数 friend void print(MyClass &s); //友元函数 public: int pub_a; static int pub_s; private: int pri_a; static int pri_s; protected: int pro_a; static int pro_s; }; //静态成员变量的初始化 int MyClass::pub_s = 100; int MyClass::pri_s = 200; int MyClass::pro_s = 300; //全局函数 void print(){ //全局函数作为类的友元,可以直接访问到类中的静态成员变量 //静态成员变量不依赖于类对象 cout << "pub_s=" << MyClass::pub_s << endl; cout << "pri_s=" << MyClass::pri_s << endl; cout << "pro_s=" << MyClass::pro_s << endl; } //全局函数 void print(MyClass &s){ //MyClass &s = m1 //全局函数作为类的友元 //不能直接访问非静态成员变量 //需要给全局函数提供一个类 类型的形参 //非静态成员变量需要依赖于类对象 s.pub_a = 100; s.pri_a = 200; s.pro_a = 300; cout << "pub_a=" << s.pub_a << endl; cout << "pri_a=" << s.pri_a << endl; cout << "pro_a=" << s.pro_a << endl; } int main(){ print(); //访问的是类中的静态成员变量 MyClass m1; print(m1); //访问的是非静态成员变量 return 0; }
#include <iostream> using namespace std; //成员函数:将一个类的成员函数作为另一个类的友元 class Date; //Date类的前置声明 // 自定义类Time class Time { public: // 构造函数 Time(int h, int m, int s) : hour(h), minute(m), second(s) { cout << "Time(int h,int m,int s)" << endl; } // 析构函数 ~Time() { cout << "~Time()" << endl; } // 打印函数 void print() { cout << hour << ":" << minute << ":" << second << endl; } //友元成员函数 //切记:Date类目前是一个不完整的类 //所以必须要实现类内声明类外实现 void Show_Date_Time(Date& d); private: int hour; // 描述小时 int minute; // 描述分钟 int second; // 描述秒 }; // 自定义Date class Date { //友元可以放在任意的权限下,我们一般放在类的开头位置上 //友元成员函数 friend void Time::Show_Date_Time(Date& d); public: // 构造函数 Date(int y, int m, int d) : year(y), month(m), day(d) { cout << "Date(int y,int m,int d)" << endl; } // 打印函数 void print() { cout << "year=" << year << "/"; cout << "month=" << month << "/"; cout << "day=" << day << endl; } private: int year; // 描述年 int month; // 描述月 int day; // 描述日 protected: }; void Time::Show_Date_Time(Date& d){ cout << hour << ":"; cout << minute << ":"; cout << second << endl; cout << d.year << "/"; cout << d.month << "/"; cout << d.day << endl; } int main() { //实例化对象 Time t1(10,12,30); Date d1(2022,11,29); t1.Show_Date_Time(d1); return 0; }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 12:17:28

创作者福音:VibeVoice让文字自动变成多人对话剧

创作者福音&#xff1a;VibeVoice让文字自动变成多人对话剧 在播客、有声书和虚拟访谈内容爆炸式增长的今天&#xff0c;一个现实问题摆在每一位内容创作者面前&#xff1a;如何高效制作自然流畅、角色鲜明的多人对话音频&#xff1f;传统方式依赖真人录音——协调时间、反复剪…

作者头像 李华
网站建设 2026/10/18 18:31:50

基于大模型的语音合成革命:VibeVoice技术深度解析

基于大模型的语音合成革命&#xff1a;VibeVoice技术深度解析 在播客、有声书和虚拟角色对话日益普及的今天&#xff0c;用户对语音内容的要求早已超越“能听就行”。人们期待的是自然流畅、富有情感张力、角色分明的对话体验——而传统文本转语音&#xff08;TTS&#xff09;系…

作者头像 李华
网站建设 2026/10/19 12:17:41

怎么把WIN11改成Win7的样子?WIN11改为win7样式

首先我们下载安装Startallback&#xff0c; 地址&#xff1a;https://pan.baidu.com/s/1qG8fXIBy_5dEu2sagc1f_Q?pwdmrnp 提取码: mrnp 注意安装的时候选择为所有人安装&#xff0c;然后右键点击开始菜单按钮&#xff0c;选择属性&#xff0c;打开软件的设置界面。 然后切换…

作者头像 李华
网站建设 2026/10/19 1:55:10

OBS多路推流插件终极指南:从安装到优化的完整教程

OBS多路推流插件终极指南&#xff1a;从安装到优化的完整教程 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 想要实现多平台同步直播却苦于技术难题&#xff1f;OBS多路推流插件正是你…

作者头像 李华
网站建设 2026/10/19 14:55:40

ChromeDriver拦截请求修改VibeVoice默认参数

ChromeDriver拦截请求修改VibeVoice默认参数 在当前AI语音内容爆发式增长的背景下&#xff0c;播客、有声书和虚拟访谈等长对话音频的需求急剧上升。用户不再满足于机械朗读式的单人TTS输出&#xff0c;而是期待具备角色区分、情感表达和长时间连贯性的“对话级”语音合成体验。…

作者头像 李华
网站建设 2026/10/19 14:07:57

screen+支持多点触控的工业场景应用详解

多点触控如何重塑工业HMI&#xff1f;——深度解析screen的实战价值你有没有遇到过这样的场景&#xff1a;在嘈杂的车间里&#xff0c;操作员戴着厚厚的手套&#xff0c;对着控制屏反复点击却毫无响应&#xff1b;或者为了调整一个参数&#xff0c;在层层嵌套的菜单中来回翻找&…

作者头像 李华