【C++】友元函数与友元类

下面详细介绍 C++ 的友元函数和友元类,并附带代码示例。

1. 友元函数 (Friend Function)

  • 概念: 友元函数是定义在类外部的普通函数,但它被声明为类的“朋友”。这意味着友元函数可以访问类的私有 (private) 和保护 (protected) 成员,就像类的成员函数一样。

  • 声明: 在类定义中使用 friend 关键字声明友元函数。

  • 目的:

    • 打破封装性: 在某些情况下,需要一个外部函数直接操作类的内部数据,而不想通过公共接口(getter/setter)进行。友元函数提供了一种受控的方式来打破封装,但仍保持一定的安全性。
    • 运算符重载: 友元函数常用于运算符重载,特别是当需要访问两个不同类的私有成员时。
    • 提高效率: 直接访问私有成员有时比通过公共接口访问更有效率,避免了函数调用的开销。
  • 注意点:

    • 友元关系是单向的。如果类 A 声明函数 f 为友元,f 可以访问 A 的私有成员,但 A 的成员函数不能访问 f 的私有数据(如果 f 是另一个类的成员函数)。
    • 友元关系不能继承。如果类 B 是类 A 的派生类,A 的友元函数不会自动成为 B 的友元函数。
    • 友元函数不是类的成员函数,因此它没有 this 指针。
  • 代码示例:

#include <iostream>

class MyClass {
private:
    int secretData;

public:
    MyClass(int data) : secretData(data) {}

    // 声明友元函数
    friend void friendFunction(const MyClass& obj);
    friend int anotherFriendFunction(const MyClass& obj);

    void printData() { //非友元函数不能访问私有成员
        std::cout << "Data from member function: " << secretData << std::endl;
    }
};

// 友元函数的定义 (在类外部)
void friendFunction(const MyClass& obj) {
    // 可以访问 MyClass 的私有成员
    std::cout << "Data from friend function: " << obj.secretData << std::endl;
}

int anotherFriendFunction(const MyClass& obj)
{
    return obj.secretData;
}

int main() {
    MyClass obj(42);
    obj.printData();        // 输出: Data from member function: 42
    friendFunction(obj);    // 输出: Data from friend function: 42
    std::cout << anotherFriendFunction(obj) << std::endl;//输出 42
    return 0;
}

2. 友元类 (Friend Class)

  • 概念: 如果一个类 A 被声明为另一个类 B 的友元类,那么类 A 的所有成员函数都可以访问类 B 的私有和保护成员。

  • 声明: 在类定义中使用 friend 关键字声明友元类。

  • 目的: 当两个类之间存在紧密合作关系,并且一个类的实现需要直接访问另一个类的内部细节时,可以使用友元类。

  • 注意点:

    • 友元关系是单向的。如果类 A 是类 B 的友元类,A 的成员函数可以访问 B 的私有成员,但 B 的成员函数不能访问 A 的私有成员。
    • 友元关系不能传递。如果类 A 是类 B 的友元,类 B 是类 C 的友元,这并不意味着类 A 是类 C 的友元。
    • 友元关系破坏了封装性,应谨慎使用。
  • 代码示例:

#include <iostream>

class ClassB;  // 前向声明

class ClassA {
public:
    void accessClassB(ClassB& obj); // 声明一个成员函数,它将访问 ClassB
};

class ClassB {
private:
    int secretData;

public:
    ClassB(int data) : secretData(data) {}

    // 声明 ClassA 为友元类
    friend class ClassA;
};

// ClassA 的成员函数定义
void ClassA::accessClassB(ClassB& obj) {
    // 可以访问 ClassB 的私有成员
    std::cout << "Accessing ClassB's secret data from ClassA: " << obj.secretData << std::endl;
}

int main() {
    ClassB objB(100);
    ClassA objA;
    objA.accessClassB(objB); // 输出: Accessing ClassB's secret data from ClassA: 100
    return 0;
}

在上面这个例子中,前向声明是必要的,因为ClassA的成员函数accessClassB的参数是ClassB的对象。
总结

友元函数和友元类提供了一种灵活的方式来允许特定的外部函数或类访问类的私有成员。虽然它们破坏了类的封装性,但在某些情况下(如运算符重载、紧密合作的类)是很有用的。然而,过度使用友元会降低代码的可维护性和可读性,因此应该谨慎使用,并仔细考虑是否有更好的替代方案(例如,通过公共接口或使用继承)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值