友元

一. 为什么要有友元?

  • C++控制类对象私有部分的访问,通常是由公有类提供唯一的访问途径,但有时候这种限制台严格。因此C++提供了友元,通过让函数成为类的友元,可以赋予函数和类成员函数相同的访问权限。
  • 友元有:友元函数、友元类、友元成员函数。

 

  • 假设有一个时间类Time,要定义时间类的乘法。我们先想到的是乘法,可以在类中重载运算符*。这样的话:
A=B*2.75; 

//相当于:
A=B.operator*(2.75);


//但却不能这样用:
A=2.75*B;
  • 也就是说重载类的*,是可以B*2.75,但却不能2.75*B。
  • 那么还有一种解决方式是,重载*运算符时,不要把函数作为类成员。如:Time operator*(double m,const Time& t); 但这样又多了一个问题,非成员函数,不能访问类的私有数据。因此就需要友元函数了。

 

二. 怎么用友元?

  • 创建友元函数的第一步是将其原型放在类声明中,并且在原型前面加上关键字friend:
friend Time operator*(double m,const Time& t);
  • 虽然它在类中声明,但它并不是类的成员函数;虽然它不是类的成员函数,但与成员函数的访问权限相同。

 

  • 定义:因为不是成员函数,定义的时候不能用Time::,也不需要加上friend。

 

<think>我们正在讨论C++中的友元函数和友元类概念。根据用户的问题,需要解释这两个概念。 引用中并没有直接关于友元的内容,但我们可以根据C++知识进行解释。 注意:用户要求使用中文回答,并且按照系统级指令格式化数学表达式(如果有的话,但本题可能没有数学表达式,所以主要关注代码格式)。 另外,需要生成相关问题。 步骤: 1. 解释友元函数:友元函数是一个非成员函数,但它可以访问类的私有(private)和保护(protected)成员。 2. 解释友元类:一个类可以声明另一个类为其友元,这样友元类就可以访问该类的私有和保护成员。 3. 注意:友元关系是单向的,不具有传递性(即A是B的友元,B是C的友元,并不意味A是C的友元)。 4. 友元破坏了封装性,因此应谨慎使用。 同时,我们将按照要求生成相关问题。 由于用户的问题中要求使用中文,所以整个回答用中文。 代码部分使用代码块格式。 注意:引用标识的使用。由于我们参考了C++的一般知识,但引用中并没有直接相关的内容,因此我们可以不添加引用标识,或者如果引用中的某些内容相关(比如静态成员)可以适当提及,但友元与静态成员无关。因此,我们主要根据知识回答,不强制添加引用标识。 但是,在回答中,我们可以提到友元函数与成员函数的区别(例如,成员函数有this指针,而友元函数没有),这时可以引用[4]中提到的静态成员函数也没有this指针,但注意友元函数不是静态成员函数,它们是非成员函数。因此,我们可以对比说明。 回答结构: 1. 友元函数 2. 友元类 3. 注意事项 4. 示例代码 5. 生成相关问题 示例代码将包括一个友元函数和一个友元类的例子。</think>### C++ 友元函数与友元类详解 #### 一、核心概念 友元(friend)是 C++ 中打破封装性的特殊机制,允许**外部函数或类访问私有成员**。主要特点: 1. **单向授权**:友元关系不可传递(A 授权 B ≠ B 自动授权 A) 2. **非继承性**:友元关系不被派生类继承 3. **精准控制**:可单独声明特定函数/类为友元 4. **语法形式**:使用 `friend` 关键字声明 #### 二、友元函数 **定义**:非成员函数访问类私有数据 ```cpp class BankAccount { private: double balance; // 私有成员 friend void audit(BankAccount&); // 友元声明 }; // 友元函数实现(无需 BankAccount::) void audit(BankAccount& acc) { std::cout << "审计访问余额: " << acc.balance; // 直接访问私有成员 } ``` **典型应用场景**: - 运算符重载(如 `<<` 流操作符) ```cpp friend std::ostream& operator<<(std::ostream& os, const MyClass& obj); ``` #### 三、友元类 **定义**:整个类访问另一类的私有成员 ```cpp class Sensor { private: int rawData; // 私有数据 friend class DataProcessor; // 友元类声明 }; class DataProcessor { public: void calibrate(Sensor& s) { s.rawData += 10; // 直接访问 Sensor 的私有成员 } }; ``` **关键限制**: - 友元关系**不对称**:`DataProcessor` 可访问 `Sensor`,反之不成立 - **不继承**:`DataProcessor` 的派生类不能访问 `Sensor` 私有成员 #### 四、注意事项与最佳实践 1. **封装破坏**:过度使用会导致代码耦合(建议优先用公有接口) 2. **前置声明**:友元类需提前声明 ```cpp class DataProcessor; // 前置声明 class Sensor { friend class DataProcessor; ... }; ``` 3. **模板特化**:友元声明在类模板中需特殊处理[^2] ```cpp template<typename T> class Box { friend void inspect<T>(Box<T>&); // 模板友元 }; ``` 4. **与静态成员对比**:友元函数无 `this` 指针,静态成员函数有类作用域但无 `this` 指针[^4] #### 五、典型错误示例 ```cpp class A { friend class B; int secret; }; class B { public: void leak(A a) { std::cout << a.secret; } // 合法 }; class C : public B { public: void fail(A a) { std::cout << a.secret; // 错误!友元关系不继承 } }; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值