news 2026/5/1 9:23:34

# 友元#

作者头像

张小明

前端开发工程师

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/5/1 3:49:20

cpp-httplib大文件传输工程实践:从内存瓶颈到高性能架构设计

cpp-httplib大文件传输工程实践&#xff1a;从内存瓶颈到高性能架构设计 【免费下载链接】cpp-httplib A C header-only HTTP/HTTPS server and client library 项目地址: https://gitcode.com/GitHub_Trending/cp/cpp-httplib 在当今数据密集型应用场景中&#xff0c;c…

作者头像 李华
网站建设 2026/5/1 3:52:23

7个Zotero插件必备技巧:快速构建高效学术工具箱

7个Zotero插件必备技巧&#xff1a;快速构建高效学术工具箱 【免费下载链接】zotero-addons Zotero add-on to list and install add-ons in Zotero 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-addons Zotero插件市场是文献管理软件的核心扩展平台&#xff0c…

作者头像 李华
网站建设 2026/5/1 3:47:41

Joy-Con Toolkit终极调校指南:专业级游戏手柄个性化配置工具

Joy-Con Toolkit终极调校指南&#xff1a;专业级游戏手柄个性化配置工具 【免费下载链接】jc_toolkit Joy-Con Toolkit 项目地址: https://gitcode.com/gh_mirrors/jc/jc_toolkit Joy-Con Toolkit是一款专为任天堂Switch手柄深度优化的开源调校工具&#xff0c;帮助玩家…

作者头像 李华
网站建设 2026/5/1 4:58:12

网页推理太方便!VibeVoice在线体验入口及部署方式

网页推理太方便&#xff01;VibeVoice在线体验入口及部署方式 在内容创作日益智能化的今天&#xff0c;你是否曾为录制一档三人对谈的播客而头疼&#xff1f;不仅要协调嘉宾时间、调试录音设备&#xff0c;还得反复剪辑才能让对话听起来自然流畅。如果有一种技术&#xff0c;只…

作者头像 李华
网站建设 2026/5/1 4:54:05

用AI编程快速验证你的创意原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 开发一个快速原型生成工具&#xff0c;能够根据用户的产品描述&#xff08;如"一个社交媒体的点赞功能"&#xff09;自动生成可运行的前端和后端代码原型。工具应支持多…

作者头像 李华
网站建设 2026/5/1 4:53:54

5分钟快速验证:JLINK接口连接方案原型

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个JLINK连接验证原型生成器&#xff0c;用户输入或选择目标板信息后&#xff0c;自动生成&#xff1a;1&#xff09;最小测试电路图&#xff08;含保护电路&#xff09;2&am…

作者头像 李华