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++ Primer Plus习题】13.4

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream>#include "port.h"int main() {Port p1;Port p2("Abc", "Bcc", 30);std::cout <<

C++包装器

包装器 在 C++ 中,“包装器”通常指的是一种设计模式或编程技巧,用于封装其他代码或对象,使其更易于使用、管理或扩展。包装器的概念在编程中非常普遍,可以用于函数、类、库等多个方面。下面是几个常见的 “包装器” 类型: 1. 函数包装器 函数包装器用于封装一个或多个函数,使其接口更统一或更便于调用。例如,std::function 是一个通用的函数包装器,它可以存储任意可调用对象(函数、函数

hdu1171(母函数或多重背包)

题意:把物品分成两份,使得价值最接近 可以用背包,或者是母函数来解,母函数(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v)(1 + x^v+x^2v+.....+x^num*v) 其中指数为价值,每一项的数目为(该物品数+1)个 代码如下: #include<iostream>#include<algorithm>

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

06 C++Lambda表达式

lambda表达式的定义 没有显式模版形参的lambda表达式 [捕获] 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 有显式模版形参的lambda表达式 [捕获] <模版形参> 模版约束 前属性 (形参列表) 说明符 异常 后属性 尾随类型 约束 {函数体} 含义 捕获:包含零个或者多个捕获符的逗号分隔列表 模板形参:用于泛型lambda提供个模板形参的名

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

【C++高阶】C++类型转换全攻略:深入理解并高效应用

📝个人主页🌹:Eternity._ ⏩收录专栏⏪:C++ “ 登神长阶 ” 🤡往期回顾🤡:C++ 智能指针 🌹🌹期待您的关注 🌹🌹 ❀C++的类型转换 📒1. C语言中的类型转换📚2. C++强制类型转换⛰️static_cast🌞reinterpret_cast⭐const_cast🍁dynamic_cast 📜3. C++强制类型转换的原因📝

C++——stack、queue的实现及deque的介绍

目录 1.stack与queue的实现 1.1stack的实现  1.2 queue的实现 2.重温vector、list、stack、queue的介绍 2.1 STL标准库中stack和queue的底层结构  3.deque的简单介绍 3.1为什么选择deque作为stack和queue的底层默认容器  3.2 STL中对stack与queue的模拟实现 ①stack模拟实现

c++的初始化列表与const成员

初始化列表与const成员 const成员 使用const修饰的类、结构、联合的成员变量,在类对象创建完成前一定要初始化。 不能在构造函数中初始化const成员,因为执行构造函数时,类对象已经创建完成,只有类对象创建完成才能调用成员函数,构造函数虽然特殊但也是成员函数。 在定义const成员时进行初始化,该语法只有在C11语法标准下才支持。 初始化列表 在构造函数小括号后面,主要用于给