友元

本文详细介绍了C++中的友元机制,包括友元类、友元函数和友元成员函数的概念及其使用方法。通过具体示例展示了如何利用友元机制实现不同类之间私有成员的访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*
有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,
这是很方便做到的。例如被重载的操作符,如输入或输出操作符,经常需要访问类的私有数据成员。
友元(frend)机制允许一个类将对其非公有成员的访问权授予指定的函数或者类,
友元的声明以friend开始,它只能出现在类定义的内部,友元声明可以出现在类中的任何地方:
友元不是授予友元关系的那个类的成员,所以它们不受其声明出现部分的访问控制影响。
通常,将友元声明成组地放在类定义的开始或结尾是个好主意。
*/

#include <iostream>  

using namespace std;




/*1.友元类
友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个
类中的隐藏信息(包括私有成员和保护成员)。当希望一个类可以存
取另一个类的私有成员时,可以将该类声明为另一类的友元类。
这里B是A的友元类
*/
class A
{
friend class B;
private:
int n = 1;
};


class B
{
public:
void method_one(A &a) {
cout << "B是A的朋友,第一种方法说出A的学号:" << a.n << endl;
}
void method_two(A &a) {
cout << "B是A的朋友,第二种方法说出A的学号:" << a.n << endl;
}
};





/**2.友元函数
友元函数是指某些虽然不是类成员函数却能够访问类的所有成员的函数。
类授予它的友元特别的访问权,这样该友元函数就能访问到类中的所有成员。
下面method_three 就是友元函数。因为声明在Class C中,所以可以访问
C的私有成员。
**/
class C
{
friend  void method_three(C &c);
private:
int n = 2;
};


void method_three(C &c) {
cout << "第三种方法能够说出C的学号:" << c.n << endl;
}






/*3.友元成员函数
下面的例子中
使类D中的成员函数成为类E的友元函数,这样类D的该成员函数就可以访问类E的所有成员了。
当用到友元成员函数时,需注意友元声明和友元定义之间的相互依赖,在该例子中,
类B必须先定义,否则类A就不能将一个B的函数指定为友元。然而,只有在定义了类A之后,
才能定义类B的该成员函数。更一般的讲,必须先定义包含成员函数的类,才能将成员函数设为友元。
*/
class E;

class D {
public:
void method_four(E &e);
};


class E {
private:
int n = 3;
public:
friend void D::method_four(E &e);
};

void D::method_four(E &e) {
cout << "第四种方法既是类D的成员函数同时又是类E的友元函数所以能够说出E的学号:" << e.n << endl;


}




int main() {
class A a;
class B b;
class C c;
class D d;
class E e;
b.method_one(a);
b.method_two(a);
method_three(c);
d.method_four(e);
system("pause");
}

<think>好的,我现在需要回答用户关于C++中友元函数和友元的定义及使用方法的问题。首先,我需要回忆自己关于友元的知识,并确保理解正确。 首先,友元函数是什么?根据引用中的内容,友元函数是一个普通函数,不属于的成员函数,但可以访问的私有和保护成员。比如在引用[1]的示例代码中,`geta`函数被声明为A的友元,因此可以直接访问A的私有成员a。同时,引用[3]提到友元函数需要在内部声明,使用`friend`关键字,然后在外定义。这一点很重要,声明友元函数的位置在的内部,而定义则可以在外部。 然后是友元友元意味着另一个的所有成员函数都可以访问当前的私有和保护成员。例如,如果B是A的友元,那么B的所有函数都能访问A的私有成员。这在引用[2]和引用[1]中都有提到,但具体的例子可能需要进一步补充。 接下来,用户可能想知道如何正确使用友元函数和友元。例如,在引用[4]中,提到了友元函数的定义格式,但用户需要注意友元函数并不是成员函数,所以定义时不需要使用作用域运算符(即不需要`名::`)。不过,这里可能存在混淆,因为引用[4]的说法可能有误,正确的友元函数定义应该是在外作为普通函数定义,而不是用名限定。比如引用[3]中的`showX`函数,定义时并没有使用`MyClass::`,而是直接作为全局函数定义。所以需要纠正引用[4]中的描述,可能是用户引用中的错误信息。 此外,友元的使用场景和注意事项也需要说明。比如,友元破坏了封装性,应谨慎使用。通常用于运算符重载或某些需要跨访问的情况。比如重载`<<`运算符时,常将其声明为友元函数,以便访问私有成员输出内容。 在回答时,需要结构清晰,分点说明友元函数和友元的定义、使用方法,并给出示例代码。同时,结合引用的内容,正确引用来源,例如引用[1]、引用[3]中的代码示例,引用[2]中的定义解释等。 还要注意用户提供的引用中有可能存在错误,需要仔细核对。例如引用[4]提到的友元函数定义格式是否准确,根据C++标准,友元函数如果是全局函数,定义时不需要名限定,而如果是另一个的成员函数作为友元,则定义时需要相应的名限定。所以可能需要更详细地解释这一点,避免用户误解。 最后,生成相关问题,确保问题与主题相关,能够帮助用户进一步学习,比如友元的优缺点、使用场景、与成员函数的区别等。</think>### C++友元函数与友元详解 #### 一、友元函数 1. **定义** 友元函数是一个**非成员函数**,但被声明为友元后,可以直接访问该的私有(`private`)和保护(`protected`)成员。通过在内使用`friend`关键字声明,例如: ```cpp class MyClass { private: int x; public: friend void showX(MyClass obj); // 声明友元函数[^3] }; ``` - **关键点**:友元函数不是的成员函数,没有`this`指针,需通过对象参数访问成员。 2. **用法示例** ```cpp #include <iostream> using namespace std; class A { public: A(int _a) : a(_a) {} friend int geta(A &ca); // 声明友元函数[^1] private: int a; }; // 定义友元函数(无需作用域::) int geta(A &ca) { return ca.a; // 直接访问私有成员a } int main() { A a(3); cout << geta(a) << endl; // 输出3 return 0; } ``` - **说明**:`geta()`在外定义,但能访问A的私有成员`a`[^1]。 --- #### 二、友元 1. **定义** 友元是指一个(如`B`)被声明为另一个(如`A`)的友元后,**B的所有成员函数**均可访问A的私有和保护成员。 ```cpp class A { friend class B; // 声明友元[^2] private: int secret; }; class B { public: void revealSecret(A &obj) { cout << obj.secret; // 直接访问A的私有成员 } }; ``` 2. **使用场景** - 当两个需要紧密协作(如数据结构和其迭代器)时。 - 需跨操作私有数据,但又不希望暴露给全局函数。 --- #### 三、注意事项 1. **封装性破坏** 友元机制破坏了封装性,过度使用会导致代码耦合性高,应谨慎使用[^3]。 2. **单向性** 友元关系是单向的。例如,若`B`是`A`的友元,`A`不自动成为`B`的友元。 3. **不可继承** 友元关系不可继承,子不会自动成为父友元。 --- #### 四、典型应用场景 1. **运算符重载** 例如重载`<<`运算符实现自定义输出: ```cpp class Point { private: int x, y; public: friend ostream& operator<<(ostream &os, const Point &p); }; ostream& operator<<(ostream &os, const Point &p) { os << "(" << p.x << ", " << p.y << ")"; // 访问私有成员 return os; } ``` 2. **跨协作** 如树(`Tree`)与节点(`Node`),节点可能需要访问树的私有成员。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值