C++ 中,友元类(Friend Class)

在 C++ 中,友元类(Friend Class) 是一种特殊的类关系,允许一个类(友元类)访问另一个类的 私有(private)保护(protected) 成员。这种机制打破了封装性,但适用于需要紧密协作的场景。

1. 基本语法

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

class ClassB {
private:
    int secretData;

    // 声明 ClassA 是 ClassB 的友元类
    friend class ClassA;  
};

class ClassA {
public:
    void accessSecret(ClassB& obj) {
        // 可以访问 ClassB 的私有成员 secretData
        std::cout << obj.secretData << std::endl;  
    }
};

2. 核心特性

  • 单向性:友元关系是单向的。 若 ClassA 是 ClassB 的友元,ClassA 可访问 ClassB 的私有成员,但 ClassB 不能访问 ClassA 的私有成员。
  • 不传递:友元关系不可继承或传递。 若 ClassA 是 ClassB 的友元,ClassA 的子类或友元类不会自动成为 ClassB 的友元。
  • 声明位置:友元类声明需在目标类内部,且不受 public/private 访问限定符影响。

3. 典型使用场景

场景 1:工具类辅助

  • 当需要设计一个工具类(如数据序列化类)直接操作另一个类的私有数据时。
class DataSerializer;  // 前向声明

class UserData {
private:
    int id;
    std::string name;

    friend class DataSerializer;  // 声明友元类
};

class DataSerializer {
public:
    static void serialize(const UserData& data) {
        // 直接访问 UserData 的私有成员
        std::cout << data.id << ", " << data.name << std::endl;
    }
};

场景 2:容器与迭代器

  • 容器类(如 MyVector)的迭代器类(如 Iterator)通常需要访问容器的私有成员。
class Iterator;  // 前向声明

class MyVector {
private:
    int* data;
    int size;

    friend class Iterator;  // 声明友元类
};

class Iterator {
public:
    Iterator(const MyVector& vec) : vec(vec) {}
    int getCurrent() {
        return vec.data[currentIndex];  // 访问 MyVector 的私有成员
    }
private:
    const MyVector& vec;
    int currentIndex = 0;
};

4. 注意事项

  • 谨慎使用:友元类破坏封装性,过度使用会导致代码耦合性高、维护困难。
  • 替代方案:优先考虑通过公共接口(如 getter/setter)访问私有数据。
  • 前向声明:若友元类未定义,需提前用 class ClassName; 前向声明。

5. 友元类 vs 友元函数

作用对象

整个类(所有成员函数)

单个函数

适用场景

需要多个函数访问私有成员

只需单个函数访问私有成员

声明方式

friend class ClassName;

friend void funcName(...);

6. 综合示例

#include <iostream>

// 前向声明
class Printer;

class Document {
private:
    std::string content;

    // 声明 Printer 是 Document 的友元类
    friend class Printer;  
public:
    Document(const std::string& text) : content(text) {}
};

class Printer {
public:
    void print(const Document& doc) {
        // 直接访问 Document 的私有成员 content
        std::cout << "Printing: " << doc.content << std::endl;
    }
};

int main() {
    Document doc("Secret Report");
    Printer printer;
    printer.print(doc);  // 输出 "Printing: Secret Report"
    return 0;
}

7. 总结

  • 友元类的作用:允许特定类直接访问私有和保护成员。
  • 适用场景:容器与迭代器、工具类辅助等紧密协作场景。
  • 代价:破坏封装性,需权衡设计需求与代码可维护性。
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务