C++中的‘friend‘关键字

目录

[友元函数(Friend Function)](#友元函数(Friend Function))

[友元类(Friend Class)](#友元类(Friend Class))

[友元函数模板(Friend Function Template)](#友元函数模板(Friend Function Template))

[友元类模板(Friend Class Template)](#友元类模板(Friend Class Template))

总结


摘要

在 C++ 中,`friend` 关键字用于声明一个函数或类为另一个类的友元,这样该函数或类可以访问这个类的私有成员和保护成员。友元机制提供了一种在保持数据封装的同时允许某些外部函数或类访问私有数据的方法。主要包含友元函数、友元类、友元函数模板、友元类模板。

友元函数(Friend Function)

友元函数是一个被指定为友元的非成员函数,它能够访问类的私有成员和保护成员。

声明和定义友元函数

cpp 复制代码
// `display` 函数被声明为 `MyClass` 的友元,因此它可以访问 `MyClass` 的私有成员 `value`
#include <iostream>

class MyClass {
public:
    MyClass(int val) : value(val) {}

    // 声明 friend 函数
    friend void display(const MyClass& obj);

private:
    int value;
};

// 定义 friend 函数
void display(const MyClass& obj) {
    std::cout << "Value: " << obj.value << std::endl;
}

int main() {
    MyClass obj(10);
    display(obj); // 输出: Value: 10
    return 0;
}

友元类(Friend Class)

友元类是一个被指定为友元的类,这样该类的所有成员函数都可以访问另一个类的私有成员和保护成员。

声明友元类

cpp 复制代码
// 类 `B` 被声明为类 `A` 的友元,因此 `B` 类中的成员函数 `showAValue` 可以访问 `A` 的私有成员 `value`
#include <iostream>

class B; // 前向声明

class A {
public:
    A(int val) : value(val) {}

    // 声明 B 为友元类
    friend class B;

private:
    int value;
};

class B {
public:
    void showAValue(const A& obj) {
        std::cout << "A's value: " << obj.value << std::endl;
    }
};

int main() {
    A a(20);
    B b;
    b.showAValue(a); // 输出: A's value: 20
    return 0;
}

友元函数模板(Friend Function Template)

我们可以将函数模板声明为友元,使得该模板实例化的每个函数都可以访问类的私有成员和保护成员。

声明友元函数模板

cpp 复制代码
// `showValue` 函数模板被声明为 `MyClass` 类模板的友元,因此它可以访问 `MyClass` 的私有成员 `value`
#include <iostream>

template <typename T>
class MyClass;

template <typename T>
void showValue(const MyClass<T>& obj);

template <typename T>
class MyClass {
public:
    MyClass(T val) : value(val) {}

    // 声明友元函数模板
    friend void showValue<>(const MyClass<T>& obj);

private:
    T value;
};

template <typename T>
void showValue(const MyClass<T>& obj) {
    std::cout << "Value: " << obj.value << std::endl;
}

int main() {
    MyClass<int> obj(30);
    showValue(obj); // 输出: Value: 30
    return 0;
}

友元类模板(Friend Class Template)

我们也可以将类模板声明为友元,使得该模板实例化的每个类都可以访问另一个类的私有成员和保护成员。

声明友元类模板

cpp 复制代码
// 类模板 `B` 被声明为类模板 `A` 的友元,因此 `B` 类模板的实例化对象可以访问 `A` 类模板的私有成员 `value`
#include <iostream>

template <typename T>
class B;

template <typename T>
class A {
public:
    A(T val) : value(val) {}

    // 声明友元类模板
    friend class B<T>;

private:
    T value;
};

template <typename T>
class B {
public:
    void showAValue(const A<T>& obj) {
        std::cout << "A's value: " << obj.value << std::endl;
    }
};

int main() {
    A<int> a(40);
    B<int> b;
    b.showAValue(a); // 输出: A's value: 40
    return 0;
}

总结

  1. 友元破坏封装:友元函数和友元类破坏了类的封装性,因为它们可以访问类的私有成员和保护成员,所以我们要谨慎使用友元机制。

  2. 友元关系单向性:友元关系是单向的。如果类 `A ` 是类 `B ` 的友元,类 `B ` 不能自动成为类 `A ` 的友元,除非也明确声明。

  3. 不能继承友元关系:友元关系不能被继承。如果基类将一个函数或类声明为友元,派生类不会自动继承这种友元关系。

  4. 滥用友元:避免滥用友元机制。如果大量使用友元,可能需要重新考虑类的设计,确保类的职责分明和接口的合理性。

友元机制在 C++ 中提供了一种在保持数据封装的同时允许某些外部函数或类访问私有数据的方法,应谨慎使用以避免破坏类的封装性和增加代码的复杂性。

相关推荐
C++ 老炮儿的技术栈1 分钟前
基于Qt实现轻量化本地音乐播放器
开发语言·c++·qt·c·播放器·音乐
qq_448011163 分钟前
C语言中的柔性数组
c语言·开发语言·柔性数组
小白学大数据6 分钟前
长周期爬虫的数据一致性:断点续爬 + 事务回滚保障采集质量
开发语言·爬虫·测试工具
leisoo809729 分钟前
财报数据怎么排雷本地化Python构建财务异常预警系统
人工智能·python·算法
zlinear数据采集卡42 分钟前
D223上位机C#开发实战:从帧解析到波形显示的完整实现
开发语言·arm开发·嵌入式硬件·fpga开发·开源·c#
Poo_Chai1 小时前
QT emit信号后完整处理流程,包括槽函数响应流程
java·开发语言·数据库
瑞码空间1 小时前
Java 图形界面(GUI)完整知识点手册
java·开发语言·图形界面·swing
小努蛋2 小时前
linux编译openresty异常问题,lua_cjson.c:706:5: 错误: ‘for‘ 循环初始化声明只在 C99 或 C++ 模式下允许
开发语言·lua·openresty
qz_Serene2 小时前
C++:类和对象(上)
开发语言·c++
西安景驰电子2 小时前
《PTP精确时间协议系列》第一篇:从原理到应用,全面解读IEEE 1588
linux·运维·服务器·开发语言·网络·windows·php