C++友元函数和友元类

关于友元函数(Friend Function)和友元类(Friend Class)的详细介绍。

友元函数(Friend Function)

定义
友元函数是一种非成员函数,但它可以访问类的私有(private)和保护(protected)成员。友元函数是通过在类定义中声明为friend来指定的。

特点

  1. 非成员函数:友元函数不是类的成员函数,因此它没有this指针。
  2. 访问权限:友元函数可以访问类的私有和保护成员。
  3. 声明位置:友元函数的声明可以在类的私有、保护或公有部分进行,但通常建议放在类的私有部分,以强调它不是类的正常接口。
  4. 定义位置:友元函数的定义可以在类定义内部或外部进行。如果定义在类外部,则不需要使用类的作用域解析运算符(::)。

用途

  • 当需要两个类紧密合作,并且一个类需要直接访问另一个类的私有成员时。
  • 实现运算符重载时,经常需要将运算符函数声明为友元,以便它可以访问类的私有数据。

友元类(Friend Class)

定义
一个类可以声明另一个类为其友元类。这意味着友元类的所有成员函数都可以访问该类的私有和保护成员。

特点

  1. 双向关系:友元关系不是双向的。如果类A是类B的友元,那么类A的成员函数可以访问类B的私有和保护成员,但类B的成员函数不能访问类A的私有和保护成员,除非类A也声明类B为其友元。
  2. 继承:如果类B是类A的友元,并且类C从类B继承,那么类C的成员函数不能访问类A的私有和保护成员,除非类A也单独声明类C为其友元。
  3. 声明位置:友元类的声明也可以在类的私有、保护或公有部分进行。

用途

  • 当两个类之间存在非常紧密的关系,并且一个类需要频繁地访问另一个类的私有成员时。
  • 在某些设计模式(如观察者模式)中,可能需要使用友元类来实现某些功能。

注意事项

  • 过度使用友元会破坏封装性,使代码更难理解和维护。因此,在设计类时,应谨慎使用友元。
  • 友元关系不能继承,也不能传递。即,如果类A是类B的友元,类B是类C的基类,那么类A不是类C的友元,除非类C也单独声明类A为其友元。

使用友元函数和友元类的详细示例

  下面是一个使用友元函数和友元类的详细示例:

#include <iostream>

// 声明一个友元类
class FriendClass;

// 定义一个类,该类有一个私有成员和一个友元函数
class MyClass {
private:
    int secretValue; // 私有成员

    // 声明一个友元函数
    friend void printSecret(MyClass& obj);
    
    // 声明一个友元类
    friend class FriendClass;

public:
    MyClass(int value) : secretValue(value) {}

    // 提供一个公共接口来读取secretValue(但不修改它)
    int getSecretValue() const { return secretValue; }
};

// 定义友元函数,该函数可以访问MyClass的私有成员
void printSecret(MyClass& obj) {
    std::cout << "Secret value from MyClass: " << obj.secretValue << std::endl;
    // 可以直接修改secretValue,因为printSecret是MyClass的友元函数
    obj.secretValue = 42; // 修改了secretValue
}

// 定义一个友元类
class FriendClass {
public:
    void increaseSecret(MyClass& obj) {
        // 可以直接访问并修改MyClass的私有成员secretValue
        obj.secretValue++;
    }
};

int main() {
    MyClass obj(10);
    std::cout << "Original secret value: " << obj.getSecretValue() << std::endl;

    // 调用友元函数
    printSecret(obj);
    std::cout << "Secret value after printSecret: " << obj.getSecretValue() << std::endl; // 应该是42

    // 使用友元类
    FriendClass friendObj;
    friendObj.increaseSecret(obj);
    std::cout << "Secret value after increaseSecret: " << obj.getSecretValue() << std::endl; // 应该是43

    return 0;
}

在这个示例中:

  • MyClass有一个私有成员secretValue
  • printSecret是一个友元函数,它可以访问并修改MyClasssecretValue
  • FriendClass是一个友元类,它的成员函数increaseSecret也可以访问并修改MyClasssecretValue

main函数中,我们创建了一个MyClass的实例obj,并初始化了它的secretValue为10。然后,我们调用了友元函数printSecret,它打印了secretValue的值,并将其修改为42。接着,我们使用FriendClass的实例friendObj调用了increaseSecret方法,该方法将secretValue增加1,使其变为43。

请注意,尽管友元函数和友元类提供了访问类私有成员的能力,但它们也破坏了封装性。因此,在实际编程中,应谨慎使用它们,并确保仅在必要时才使用。

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值