C++ 友元函数和友元类

2023-10-21 14:12
文章标签 c++ 函数 友元 友元类

本文主要是介绍C++ 友元函数和友元类,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

        在本文中,您将学习在C ++中创建友元函数和友元类,并在程序中有效地使用它们。OOP的重要概念之一是数据隐藏,即非成员函数无法访问对象的私有或受保护的数据。但是,有时这种限制可能迫使程序员编写冗长而复杂的代码。因此,C ++编程内置了一种机制,可以从非成员函数访问私有或受保护的数据,这是使用友元函数和友元类完成的。

C ++中的友元函数

        如果将函数定义为友元函数,则可以使用函数访问类的私有数据和受保护数据。通过使用关键字friend,编译器知道给定的函数是友元函数。要访问数据,应该在类的内部以关键字friend开始声明友元函数(可以是类内部的任何地方,可以是private部分,也可以是public部分)。

C ++中的友元函数声明

class class_name
{... .. ...friend return_type function_name(argument/s);... .. ...
}

现在,您可以将友元函数定义为访问该类数据的普通函数。friend定义中未使用任何关键字。

class className
{... .. ...friend return_type functionName(argument/s);... .. ...
}return_type functionName(argument/s)
{... .. ...// 可以从这个位置访问className的私有和受保护数据//因为此函数是className的友元函数。... .. ...
}

 

/* C ++程序演示友元函数的工作。*/
#include<iostream>
class base {
public:// 友元函数friend int display_friend(base);
private:int a = 1;
protected:int b = 2;
};// 友元函数的定义
int display_friend(base m) {//从非成员函数访问私有数据和受保护数据int c = m.a + m.b;return c;
}int main() {base base1;std::cout << "输出:" << display_friend(base1) << std::endl;system("pause");return 0;
}

输出结果:

3

分析:

        这里,友元函数display_friend() 在base类中声明。因此,可以从这个函数访问类中的私有数据和受保护数据。

若将友元函数在类中的声明去掉,则程序会报错:
去掉友元函数在类中的声明之后代码如下:

/* C ++程序演示友元函数的工作。*/
#include<iostream>
class base {
public:// 友元函数//friend int display_friend(base);
private:int a = 1;
protected:int b = 2;
};// 友元函数的定义
int display_friend(base m) {//从非成员函数访问私有数据和受保护数据int c = m.a + m.b;return c;
}int main() {base base1;std::cout << "输出:" << display_friend(base1) << std::endl;system("pause");return 0;
}

编译器报错: 

使用友元函数添加两个不同类的私有或受保护成员变量

#include<iostream>
class base2; // 类base2的前置声明class base1 {
public:// 友元函数声明friend int display_friend(base1, base2);
private:int a = 1;
};class base2 {
public:// 友元函数声明friend int display_friend(base1, base2);protected:int b = 2;
};// 友元函数的定义
// 函数display_friend()是类base1和base2的友元函数
int display_friend(base1 m1, base2 m2) {//从非成员函数访问私有数据和受保护数据int c = m1.a + m2.b;return c;
}int main() {base1 A;base2 B;std::cout << "输出:" << display_friend(A, B) << std::endl;system("pause");return 0;
}

 输出结果:

3

分析:

        在这个程序中,类base1和base2已经将display_friend()声明为friend函数。因此,这个函数可以访问这两个类的私有数据或受保护数据。在这里,display_friend()函数将两个对象A和B的私有数据 a 和受保护数据 b 相加,并将其返回给main函数。

        为了使这个程序正常工作,应该像上面的实例中所示的那样,对一个类base2进行前置声明。这是因为使用以下代码在class base1中引用了class base2的友元函数:friend int display_friend(base1,base2);

友元类(friend class)

        类似地,像一个友元函数一样,一个类也可以使用关键字friend成为另一个类的友元类。例如:

... .. ...
class B;
class A
{// class B 是 class A的友元类friend class B;... .. ...
}class B
{... .. ...
}

        当一个类成为另一个类的friend类(友元类)时,这就意味着这个类的所有成员函数都是另一个类的友元函数。

        在这个程序中,B类的所有成员函数都是A类的朋友函数,因此B类的任何成员函数都可以访问A类的私有和受保护的数据,但是A类的成员函数不能访问B类的数据。

例如下面的代码:

#include<iostream>
class B; // 前置声明class A {// class B 是class A的友元类friend class B;private:int a = 1;
protected:int b = 2;
};class B {public:// 类B的成员函数int displayB(A a1) {int c = a1.a + a1.b;return c;}
};int main() {A a2;B b2;std::cout << b2.displayB(a2) << std::endl;
}

输出结果:

3

分析: 

        类B 为类A 的友元类,类B中的成员函数可以访问类A的私有数据和受保护数据。

C ++编程中如何互为友元类

        如何实现classA与B互为友元,即A可以访问B的私有,B也可以访问A的私有呢?案例如下:

#include<iostream>
class B; // 前置声明class A {// class B 是class A的友元类friend class B;private:int a = 1;
protected:int b = 2;
public:int displayA(B);
};class B {// class A 是class B 的友元类friend class A;public:// 类B的成员函数int displayB(A a1) {int c = a1.a + a1.b;return c;}
private:int e = 3;
protected:int f = 4;
};// 类A的成员函数
int A::displayA(B b1) {int g = b1.e + b1.f;return g;
}int main() {A a2;B b2;std::cout << b2.displayB(a2) << std::endl; // 3std::cout << a2.displayA(b2) << std::endl; // 7
}

输出结果:
3
7

互为友元类的做法就是,在class A中声明friend class B;在classB 中声明friend class A;

注意:类A中使用到了类B的地方必须在类B的声明后定义,在类A中只能声明。例如上边类A中的displayA() 函数,不能在类A中直接定义,只能放在类B的声明之后定义。

这篇关于C++ 友元函数和友元类的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/254923

相关文章

C++快速排序超详细讲解

《C++快速排序超详细讲解》快速排序是一种高效的排序算法,通过分治法将数组划分为两部分,递归排序,直到整个数组有序,通过代码解析和示例,详细解释了快速排序的工作原理和实现过程,需要的朋友可以参考下... 目录一、快速排序原理二、快速排序标准代码三、代码解析四、使用while循环的快速排序1.代码代码1.由快

C语言字符函数和字符串函数示例详解

《C语言字符函数和字符串函数示例详解》本文详细介绍了C语言中字符分类函数、字符转换函数及字符串操作函数的使用方法,并通过示例代码展示了如何实现这些功能,通过这些内容,读者可以深入理解并掌握C语言中的字... 目录一、字符分类函数二、字符转换函数三、strlen的使用和模拟实现3.1strlen函数3.2st

VSCode中C/C++编码乱码问题的两种解决方法

《VSCode中C/C++编码乱码问题的两种解决方法》在中国地区,Windows系统中的cmd和PowerShell默认编码是GBK,但VSCode默认使用UTF-8编码,这种编码不一致会导致在VSC... 目录问题方法一:通过 Code Runner 插件调整编码配置步骤方法二:在 PowerShell

C/C++随机数生成的五种方法

《C/C++随机数生成的五种方法》C++作为一种古老的编程语言,其随机数生成的方法已经经历了多次的变革,早期的C++版本使用的是rand()函数和RAND_MAX常量,这种方法虽然简单,但并不总是提供... 目录C/C++ 随机数生成方法1. 使用 rand() 和 srand()2. 使用 <random

MySQL中COALESCE函数示例详解

《MySQL中COALESCE函数示例详解》COALESCE是一个功能强大且常用的SQL函数,主要用来处理NULL值和实现灵活的值选择策略,能够使查询逻辑更清晰、简洁,:本文主要介绍MySQL中C... 目录语法示例1. 替换 NULL 值2. 用于字段默认值3. 多列优先级4. 结合聚合函数注意事项总结C

Win32下C++实现快速获取硬盘分区信息

《Win32下C++实现快速获取硬盘分区信息》这篇文章主要为大家详细介绍了Win32下C++如何实现快速获取硬盘分区信息,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 实现代码CDiskDriveUtils.h#pragma once #include <wtypesbase

C++ Primer 标准库vector示例详解

《C++Primer标准库vector示例详解》该文章主要介绍了C++标准库中的vector类型,包括其定义、初始化、成员函数以及常见操作,文章详细解释了如何使用vector来存储和操作对象集合,... 目录3.3标准库Vector定义和初始化vector对象通列表初始化vector对象创建指定数量的元素值

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链

MySQL 日期时间格式化函数 DATE_FORMAT() 的使用示例详解

《MySQL日期时间格式化函数DATE_FORMAT()的使用示例详解》`DATE_FORMAT()`是MySQL中用于格式化日期时间的函数,本文详细介绍了其语法、格式化字符串的含义以及常见日期... 目录一、DATE_FORMAT()语法二、格式化字符串详解三、常见日期时间格式组合四、业务场景五、总结一、

C++实现回文串判断的两种高效方法

《C++实现回文串判断的两种高效方法》文章介绍了两种判断回文串的方法:解法一通过创建新字符串来处理,解法二在原字符串上直接筛选判断,两种方法都使用了双指针法,文中通过代码示例讲解的非常详细,需要的朋友... 目录一、问题描述示例二、解法一:将字母数字连接到新的 string思路代码实现代码解释复杂度分析三、