【030】C++类和对象之友元(friend)详解

这篇具有很好参考价值的文章主要介绍了【030】C++类和对象之友元(friend)详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

引言


💡 作者简介:专注于C/C++高性能程序设计和开发,理论与代码实践结合,让世界没有难学的技术。包括C/C++、Linux、MySQL、Redis、TCP/IP、协程、网络编程等。
👉
🎖️ CSDN实力新星,社区专家博主
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【029】C++静态成员和 this 指针详解

一、友元概述

C++中,友元(friend)是一种机制,它允许一个类的非成员函数或另一个类访问该类的私有成员。友元可以在类定义中声明,在类定义外部实现。

类的主要特点之一是数据隐藏,即类的私有成员无法在类的外部作用域之外访问。但是有时候需要在类的外部访问类的私有成员,因此出现了友元函数;友元函数是一种特权函数,允许访问私有成员。可以把一个全局函数、或者类的成员函数、甚至整个类声明为友元。

需要注意的是,友元机制破坏了类的封装性,因此应该谨慎使用。如果过度使用友元机制,会导致代码难以维护和扩展。

二、友元的语法

使用friend关键字声明为友元。声明一个友元函数或友元类的语法如下:

(1)友元函数的声明语法。

class ClassName {
private:
    // 私有成员
public:
    friend ReturnType FunctionName(ParameterList); // 声明友元函数
};

其中,ClassName为当前类名,ReturnType为友元函数的返回类型,FunctionName为友元函数名,ParameterList为参数列表。

(2)友元类的声明语法。

class ClassName1 {
private:
    // 私有成员
public:
    friend class ClassName2; // 声明友元类
};

其中,ClassName1为当前类名,ClassName2为被声明为友元的类名。

需要注意的是,在程序中定义和实现了一个被声明为该类的友元的全局函数或其他类中的成员函数时,在该函数前需要加上 friend ClassName::FunctionName() 来指定这个函数是属于哪个类。例如:

class MyClass {
private:
    int privateMember;

public:
    friend void friendFunction(MyClass obj);
};

void friendFunction(MyClass obj) {
    cout << "The value of private member is: " << obj.privateMember;
}

int main() {
    MyClass myObj;
    
    myObj.privateMember = 10;
    
    friendFunction(myObj); // 调用友元函数
    
    return 0;
}

如果将 friendFunction() 函数定义放在 MyClass 类外面,则需要使用以下语法:

void friend MyClass::friendFunction(MyClass obj) { ... }

三、友元的应用举例

3.1、普通全局函数作为类的友元

#include <iostream>
#include <string>
using namespace std;
class Room {
	friend int visiting(Room &room);
private:
	string bedRoom;//私有
public:
	string setingRoom;//公共
public:

	Room(string bedRoom, string setingRoom)
	{
		this->bedRoom = bedRoom;
		this->setingRoom = setingRoom;
	}
};

// 普通全局函数
int visiting(Room &room)
{
	cout << room.setingRoom << endl;
	cout << room.bedRoom << endl;//如果没有设置友元则无法访问
	return 0;
}

int main()
{
	Room room("Bed", "seting");
	visiting(room);
	return 0;
}

3.2、类的某个成员函数作为另一个类的友元

#include <iostream>
#include <string>
using namespace std;

class Room;// 向前声明,只能说明类名称

class Good {
public:
	int visiting01(Room &room);
	int visiting02(Room &room);
};
class Room {
	friend int Good::visiting02(Room &room);
private:
	string bedRoom;//私有
public:
	string setingRoom;//公共
public:

	Room(string bedRoom, string setingRoom)
	{
		this->bedRoom = bedRoom;
		this->setingRoom = setingRoom;
	}
};

// 成员函数
int Good::visiting01(Room &room)
{
	cout << room.setingRoom << endl;
	//cout << room.bedRoom << endl;// error
	return 0;
}

int Good::visiting02(Room &room)
{
	cout << room.setingRoom << endl;
	cout << room.bedRoom << endl;//如果没有设置友元则无法访问
	return 0;
}

int main()
{
	Room room("Bed", "seting");
	Good good;
	good.visiting01(room);
	good.visiting02(room);
	return 0;
}

3.3、整个类作为另一个类的友元

#include <iostream>
#include <string>
using namespace std;

class Room;// 向前声明,只能说明类名称
class Good {
public:
	int visiting01(Room &room);
	int visiting02(Room &room);
};
class Room {
	friend class Good;
private:
	string bedRoom;//私有
public:
	string setingRoom;//公共
public:

	Room(string bedRoom, string setingRoom)
	{
		this->bedRoom = bedRoom;
		this->setingRoom = setingRoom;
	}
};

// 成员函数
int Good::visiting01(Room &room)
{
	cout << room.setingRoom << endl;
	cout << room.bedRoom << endl;// OK
	return 0;
}

int Good::visiting02(Room &room)
{
	cout << room.setingRoom << endl;
	cout << room.bedRoom << endl;//如果没有设置友元则无法访问
	return 0;
}

int main()
{
	Room room("Bed", "seting");
	Good good;
	good.visiting01(room);
	good.visiting02(room);
	return 0;
}

四、友元的注意事项

  1. 友元函数可以访问类的私有成员和保护成员,因此需要谨慎使用。过度使用友元函数可能会破坏类的封装性,导致代码难以维护。

  2. 友元关系不能被继承。即使是派生类也不能访问基类中声明为友元的函数或类。

  3. 友元关系是单向的。如果A是B的友元,那么B并不一定是A的友元。

  4. 在定义友元函数时,需要在函数名前加上关键字“friend”,同时在类定义中声明该函数。

  5. 友元关系不具备传递性。即如果A是B的友元,B是C的友元,并不意味着A也是C的友元。

  6. 可以将一个类声明为另一个类的友元,这样就可以让该类中所有成员都能够访问另一个类中的私有成员和保护成员。

  7. 如果一个函数需要访问多个类中的私有成员和保护成员,可以将其声明为这些类中任意一个类的友元即可。

五、友元案例

设计一个电视机类,电视机属性有:

  • 开机和关机;
  • 音量;
  • 频道;
  • 操作音量的方法;
  • 操作频道的方法。

电视机只能逐一调整频道,不能指定频道。添加遥控类,遥控类除了拥有电视机 已有功能,再添加根据输入调台功能。

将遥控器类作为电视机类的友元类。

class TV;

class Remote {
private:
	TV *p;
public:
	Remote(TV *p)
	{
		this->p = p;
	}
	void onOrOff();
	void upVolume();
	void downVolume();
	void upChannel();
	void downChannel();
	void showTV();
	void setChannel(int num);
};


class TV {
	friend class Remote;
	enum{OFF,ON};
	enum{minVol,maxVol=100};
	enum{minChannel,maxChannel=28};
private:
	int status;
	int volume;
	int channel;
public:
	TV()
	{
		status = OFF;
		volume = minVol;
		channel = minChannel;
	}
	void onOrOff();
	void upVolume();
	void downVolume();
	void upChannel();
	void downChannel();
	void showTV();
};

void TV::onOrOff()
{
	status = (status == OFF ? ON : OFF);
}

void TV::upVolume()
{
	if (volume >= maxVol)
	{
		cout << "音量已经最大啦" << endl;
		return;
	}
	volume++;
}
void TV::downVolume()
{
	if (volume < minVol)
	{
		cout << "音量已经最小啦" << endl;
		return;
	}
	volume--;
}

void TV::upChannel()
{
	if (channel >= maxChannel)
	{
		cout << "频道已经最大啦" << endl;
		return;
	}
	channel++;
}
void TV::downChannel()
{
	if (channel < minChannel)
	{
		cout << "频道已经最小啦" << endl;
		return;
	}
	channel--;
}

void TV::showTV()
{
	cout << "电视机状态:" << (status == OFF ? "关" : "开") << endl;
	cout << "电视频道:" << channel << endl;
	cout << "电视音量:" << volume << endl;
	cout << "------------------------------------" << endl;
}

// -----------------------------------------
void Remote::onOrOff()
{
	p->onOrOff();
}

void Remote::upVolume()
{
	p->upVolume();
}
void Remote::downVolume()
{
	p->downVolume();
}

void Remote::upChannel()
{
	p->upChannel();
}
void Remote::downChannel()
{
	p->downVolume();
}

void Remote::showTV()
{
	p->showTV();
}

void Remote::setChannel(int num)
{
	if (num >= TV::minChannel && num<=TV::maxChannel)
	{
		p->channel = num;
		return;
	}
	cout << "输入的频道不合法" << endl;
}


int main()
{
	TV tv;
	tv.showTV();
	
	tv.onOrOff();
	tv.upChannel();
	tv.upChannel();
	tv.upVolume();
	tv.showTV();
	tv.onOrOff();

	cout << "使用遥控器:" << endl;
	Remote rtv(&tv);
	rtv.showTV();

	rtv.onOrOff();
	rtv.upChannel();
	rtv.upChannel();
	rtv.downChannel();
	rtv.upVolume();
	rtv.showTV();
	rtv.onOrOff();

	return 0;
}

输出:

电视机状态:关
电视频道:0
电视音量:0
------------------------------------
电视机状态:开
电视频道:2
电视音量:1
------------------------------------
使用遥控器:
电视机状态:关
电视频道:2
电视音量:1
------------------------------------
电视机状态:开
电视频道:4
电视音量:1
------------------------------------

总结

  1. 友元函数。

友元函数是一个普通的非成员函数,但它被声明为某个类的友元。这意味着该函数可以访问该类的所有私有成员和保护成员。声明方式为在类定义中使用“friend”关键字,例如:

class MyClass {
  friend void myFunction();
};
  1. 友元类。

友元类是指某个类A将另一个类B声明为自己的友元,在这种情况下,B可以访问A的私有成员和保护成员。声明方式为在类定义中使用“friend”关键字并加上要作为友元的类名,例如:

class MyClass {
  friend class MyFriendClass;
};
  1. 友元成员函数。

友元成员函数是指某个函数被声明为另一个类A的友元,并且该函数所属于另一个与A无关的类B。这意味着该函数可以访问A对象中所有私有成员和保护成员。声明方式为在B类定义中使用“friend”关键字和A类型参数,例如:

class MyClassA {
  friend void MyClassB::myFunction(MyClassA&);
};
  1. 友元作用域。

友元的作用域是在声明它的类中,而不是在被声明为友元的函数或类中。因此,在同一作用域中可以使用相同名称的友元,但它们分别属于不同的类。

  1. 友元与继承。

子类不能直接访问父类的私有成员,但如果将子类声明为父类的友元,则子类就可以访问父类的私有成员和保护成员。这种情况下,应该谨慎考虑是否破坏了封装性。

【030】C++类和对象之友元(friend)详解文章来源地址https://www.toymoban.com/news/detail-494483.html

到了这里,关于【030】C++类和对象之友元(friend)详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C++】类和对象详解(类的使用,this指针)

    提示:这里可以添加本文要记录的大概内容: 在计算机编程领域,程序设计的方法论不断演化,从最初的面向过程到如今更为强大而灵活的面向对象。本文将深入探讨C++中关于类和对象的概念,为读者提供对面向对象编程的深刻理解。 提示:以下是本篇文章正文内容,下面

    2024年02月02日
    浏览(42)
  • 一文带你入门C++类和对象【十万字详解,一篇足够了】

    本文字数较多,建议电脑端访问。不多废话,正文开始 从本文开始,我们就要正式来学习C++中的类和对象了,本文我将带你一步步 从C语言的结构体 struct 到C++的类 class ,真正搞懂有关C++的 面向对象的三大特征之一 —— 封装 作为读者,可能你正在学习C语言,亦或者已经开

    2024年02月05日
    浏览(47)
  • <C++> 类和对象-面向对象

    C语言是 面向过程 的,关注的是过程,分析出求解问题的步骤, 通过函数调用逐步解决问题。 C++是基于 面向对象 的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。 C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函

    2024年02月14日
    浏览(46)
  • <C++> 类和对象(上)-面向对象

    C语言是 面向过程 的,关注的是过程,分析出求解问题的步骤, 通过函数调用逐步解决问题。 C++是基于 面向对象 的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。 C语言结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函

    2024年02月11日
    浏览(53)
  • C++:类和对象(中)

    如果一个类中什么成员都没有,简称为空类。 空类中真的什么都没有吗?并不是,任何类在什么都不写时, 编译器会自动生成以下6个默认成员函数。 默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数 class Date {}; 对于Date类,可以通过 Init 公有方

    2024年02月03日
    浏览(45)
  • 【C++】类和对象-封装

    在main函数前重新补上isSame函数 在Cube类里面添加issamebyclass,利用成员函数判断两个立方体是否相等 自己写的代码: B站视频链接: https://www.bilibili.com/video/BV1et411b73Z/?p=105spm_id_from=333.1007.top_right_bar_window_history.content.clickvd_source=fb8dcae0aee3f1aab700c21099045395

    2024年02月15日
    浏览(48)
  • C++——类和对象(2)

    当一个类中什么都没有,编译器会帮类自动生成6个默认成员函数例如: 此篇文章主要围绕构造函数与析构函数进行讲解。  对于以上的Date类,每次实例化对象之后都要对对象调用Init()函数,比较繁琐,其实编译器就可以帮我们完成。 构造函数是一个特殊的成员函数,名字与

    2024年03月17日
    浏览(48)
  • 【C++】类和对象(四)

    前言:在类和对象中,我们走过了十分漫长的道路,今天我们将进一步学习类和对象,类和对象这块荆棘地很长,各位一起加油呀。 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:高质量C++学习 👈 💯代码仓库:卫卫周大胖的学习日记💫 💪关注博主和博主一起学习

    2024年02月19日
    浏览(34)
  • 【C++】:类和对象(1)

    朋友们、伙计们,我们又见面了,本期来给大家解读一下有关C++中类和对象的知识点,如果看完之后对你有一定的启发,那么请留下你的三连,祝大家心想事成! C 语 言 专 栏: C语言:从入门到精通 数据结构专栏: 数据结构 个  人  主  页 : stackY、 目录 1.面向过程和面

    2024年02月08日
    浏览(37)
  • 【C++】类和对象(上)

    个人主页:平行线也会相交 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C++之路】 C语言是面向过程的,而C++是面向对象的,那面向过程和面向对象到底是什么呢? 我们拿一个非常典型的 外卖系统 来进行举例: 面向过程: 我们知道外面

    2024年02月02日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包