C++ :友元类

news2024/12/24 8:33:22

友元类的概念和使用

(1)将类A声明为B中的friend class后,则A中所有成员函数都成为类B的友元函数了
(2)代码实战:友元类的定义和使用友元类是单向的
(3)友元类是单向的,代码实战验证

互为友元类

(1)2个类可以互为友元类,代码实战验证
(2)互为友元类要注意互相引用的细节规则

(1)友元类其实就是批量制造友元函数
(2)友元类中所有全部成员都成为了友元函数,相当于一次打了很多洞,极大破坏了面向对象
(3)除非确实有必要,否则建议按需定义友元函数,尽量维护面向对象,让代码更安全健壮

#include <iostream>
#include <string>

class Country;  // Forward declaration of Country

// External friend function declaration
void disp_info_external(const Country &ct);

class InfoDisplayer {
 public:
  // Member function declaration
  void disp_info_member(const Country &ct) const;
};

class InfoFriendClass {
 public:
  // Member function to display information
  void display(const Country &ct) const;
};

class Country {
 private:
  std::string privateName;

 protected:
  int protectedPopulation;

 public:
  std::string publicCapital;

  // Constructor
  Country(std::string name, int population, std::string capital)
      : privateName(name),
        protectedPopulation(population),
        publicCapital(capital) {}

  // Friend function declaration
  friend void disp_info_external(const Country &ct);
  // friend void InfoDisplayer::disp_info_member(const Country &ct);//error: no
  // declaration matches ‘void InfoDisplayer::disp_info_member(const Country&)’
  friend class InfoFriendClass;  // Friend class declaration
};

// Definition of the external friend function
void disp_info_external(const Country &ct) {
  std::cout << "disp_info_external Name: " << ct.privateName << "\n";
  std::cout << "disp_info_external Population: " << ct.protectedPopulation
            << "\n";
  std::cout << "disp_info_external Capital: " << ct.publicCapital << "\n";
}

// Definition of the member friend function
void InfoDisplayer::disp_info_member(const Country &ct) const {
  // std::cout << "disp_info_member Name: " << ct.privateName << "\n";

  // error: ‘int Country::protectedPopulation’ is protected within this context
  //  std::cout << "disp_info_member Population: " << ct.protectedPopulation <<
  //  "\n"; std::cout << "disp_info_member Capital: " << ct.publicCapital <<
  //  "\n";
}

// Definition of the friend class member function
void InfoFriendClass::display(const Country &ct) const {
  std::cout << "InfoFriendClass Name: " << ct.privateName << "\n";
  std::cout << "InfoFriendClass Population: " << ct.protectedPopulation << "\n";
  std::cout << "InfoFriendClass Capital: " << ct.publicCapital << "\n";
}

int test070401() {
  // Create an object of Country
  Country myCountry("Wonderland", 5000000, "Magic City");

  // Display information using the external friend function
  disp_info_external(myCountry);

  // Create an object of InfoDisplayer
  InfoDisplayer displayer;

  // Display information using the member friend function
  displayer.disp_info_member(myCountry);

  // Create an object of InfoFriendClass
  InfoFriendClass friendClass;

  // Display information using the friend class member function
  friendClass.display(myCountry);

  return 0;
}

在这里插入图片描述

#include <iostream>
#include <string>

class Vegetable;  // Forward declaration of Vegetable

class Fruit {
 private:
  std::string name;

 protected:
  std::string color;

 public:
  // Constructor
  Fruit(std::string n, std::string c) : name(n), color(c) {}

  // Friend class declaration
  friend class Vegetable;

  // Definition of the friend function
  void displayVegetable(const Vegetable &veg);
};

class Vegetable {
 private:
  std::string name;

 protected:
  std::string color;

 public:
  // Constructor
  Vegetable(std::string n, std::string c) : name(n), color(c) {}

  // Friend class declaration
  friend class Fruit;

  // Member function declaration
  void displayFruit(const Fruit &fruit) const {
    std::cout << "Vegetable accessing Fruit's name: " << fruit.name << "\n";
    std::cout << "Vegetable accessing Fruit's color: " << fruit.color << "\n";
  }
};

void Fruit::displayVegetable(const Vegetable &veg) {
  std::cout << "Fruit accessing Vegetable's name: " << veg.name << "\n";
  std::cout << "Fruit accessing Vegetable's color: " << veg.color << "\n";
}

int test070402() {
  // Create objects of Fruit and Vegetable
  Fruit apple("Apple", "Red");
  Vegetable spinach("Spinach", "Green");


  apple.displayVegetable(spinach);

  // Display information using the member function of Vegetable
  spinach.displayFruit(apple);

  return 0;
}

在这里插入图片描述

为什么会有友元函数

使用友元函数的优缺点
(1)缺点:破坏了封装机制,尽量不使用友元函数,不得已才使用友元函数
(2)优点:在实现类之间数据共享时,减少系统开销,提高效率。

使用友元函数的两种情况
(1)运算符重载的某些场合需要使用友元
(2)两个类要共享数据的时候
两个类如何共享数据
(1)类内的数据,其实就是类的成员变量
(2)2个类共享数据方法1:将共享数据访问权限设置为public。
(3)2个类共享数据方法2:通过第三个专门封装数据的类,和2个类中带参数的成员函数来传参共享
(4)2个类共享数据方法3:通过友元函数打洞

友元函数和类的成员函数的区别
(1)成员函数有this指针,而友元函数没有this指针。为什么?因为友元只是朋友,并不是类内“自家人”
(2)友元函数是不能被继承的,就像父亲的朋友未必是儿子的朋友。
(3)友元关系不具有传递性。类B是类A的友元,类C是B的友元,类C不一定是类A的友元,要看类中是否有相应的声明

共有友元函数
(1)1个函数同时成为2个类的友元函数
(2)共有友元函数可以是外部函数,也可以是某个(第3个)类的成员函数
(3)共有友元函数内可同时访问2个类的受保护成员,间接将2个完全无关的类的数据打通了

总结

有元函数是单向的
两个类可以互为有元类、可以相互拥有有元方法
C++编译器在寻找运算符函数时,找的自己内部的函数,有就用显示实现的函数,没有的话就使用默认实现的,有元函数是外部函数,就不太编译器寻找范围内

学习记录,侵权联系删除。
来源:朱老师物联网大课堂

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1936770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

相同IP地址仿真测试

相同IP地址仿真测试 背景与挑战解决方案技术优势功能特点 背景与挑战 在汽车电子领域&#xff0c;电子控制单元&#xff08;ECU&#xff09;的测试是确保其功能性和可靠性的关键步骤。然而&#xff0c;当测试场景涉及多个配置相同IP地址的ECU时&#xff0c;传统的测试方法面临…

GooglePlay 金融品类政策更新(7月17号)

距离上次政策大更新&#xff08;4月5号&#xff09;才过去了3个月&#xff0c;Google Play又迎来了一次大更新&#xff0c;不得不说Google Play的要求越来越高了。 我们来梳理一下这次GooglePlay针对金融品类更新了哪些政策: 1.要求提供金融产品和服务的开发者必须注册为组织…

IDEA的常见代码模板的使用

《IDEA破解、配置、使用技巧与实战教程》系列文章目录 第一章 IDEA破解与HelloWorld的实战编写 第二章 IDEA的详细设置 第三章 IDEA的工程与模块管理 第四章 IDEA的常见代码模板的使用 第五章 IDEA中常用的快捷键 第六章 IDEA的断点调试&#xff08;Debug&#xff09; 第七章 …

STM32使用SPI向W25Q64存储信息(HAL库)

SPI全双工通信&#xff1a;全双工在时钟脉冲周期的每一个周期内&#xff0c;每当主设备同时发送一个字节的同时&#xff0c;会接受从设备接受一个字节数据&#xff0c;SPI全双工最大的特点就是发送和接受数据同步进行&#xff0c;发送多少数据就要接受多少数据。使用全双工通信…

vst 算法R语言手工实现 | Seurat4 筛选高变基因的算法

1. vst算法描述 &#xff08;1&#xff09;为什么需要矫正 image source: https://ouyanglab.com/singlecell/basic.html In this panel, we observe that there is a very strong positive relationship between a gene’s average expression and its observed variance. I…

【iOS】static、extern、const、auto关键字以及联合使用

目录 前言extern关键字static关键字const关键字 联合使用static和externstatic和constextern和const auto关键字 先了解一下静态变量所在的全局/静态区的特点&#xff1a;【iOS】内存五大分区 前言 上面提到的全局/静态区中存放的是全局变量或静态变量&#xff1a; 全局变量…

逻辑回归(Logistic Regression,LR)

分类和回归是机器学习的两个主要问题。 分类处理的是离散数据回归处理的是连续数据 线性回归&#xff1a;回归 拟合一条线预测函数&#xff1a; 逻辑回归&#xff1a;分类——找到一条线可以将不同类别区分开 虽然称为逻辑回归&#xff0c;但是实际是一种分…

Chromium CI/CD 之Jenkins实用指南2024-在Windows节点上创建任务(九)

1. 引言 在现代软件开发流程中&#xff0c;持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;已成为确保代码质量和加速发布周期的关键实践。Jenkins作为一款广泛应用的开源自动化服务器&#xff0c;通过其强大的插件生态系统和灵活的配置选项&#xf…

【第4章】Spring Cloud之Nacos单机模式支持mysql

文章目录 前言一、初始化1. 初始化数据库2. 修改配置文件 二、效果1. 重新启动2. 新增用户 总结 前言 在0.7版本之前&#xff0c;在单机模式时nacos使用嵌入式数据库实现数据的存储&#xff0c;不方便观察数据存储的基本情况。0.7版本增加了支持mysql数据源能力&#xff0c;具…

数据如光,科技助航丨泰迪智能科技2024年暑期数据分析学徒班正式开班

7月16日&#xff0c;泰迪智能科技2024年暑期数据分析学徒班在泰迪智能科技天河培训中心正式开班&#xff0c;泰迪智能科技培训业务部孙学镂、教学代表周津、授课讲师巫兴港、就业指导老师赵欣欣、孟宪同、教学班主任黄晨华出席此次开班仪式。 仪式伊始&#xff0c;孙学镂代表广…

达梦数据库的系统视图v$arch_status

达梦数据库的系统视图v$arch_status 在达梦数据库&#xff08;DM Database&#xff09;中&#xff0c;V$ARCH_STATUS 是一个动态性能视图&#xff08;Dynamic Performance View&#xff09;&#xff0c;用于显示归档日志的状态信息。这个视图可以帮助数据库管理员监控和管理数…

【Linux服务器Java环境搭建】010在linux中安装Redis,以及对Redis的配置与远程连接

系列文章目录 【Linux服务器Java环境搭建】 前言 好久没有更新博客了&#xff0c;今天下了班回到家&#xff0c;看到电脑桌上尘封已久的《Spring Boot应用开发实战》&#xff0c;翻开目录想起来之前写的系列【Linux服务器Java环境搭建】还未完结&#xff0c;那就继续吧&#…

通义千问AI模型对接飞书机器人-模型配置(2-1)

一 背景 根据业务或者使用场景搭建自定义的智能ai模型机器人&#xff0c;可以较少我们人工回答的沟通成本&#xff0c;而且可以更加便捷的了解业务需求给出大家设定的业务范围的回答&#xff0c;目前基于阿里云的通义千问模型研究。 二 模型研究 参考阿里云帮助文档&#xf…

IDEA的断点调试(Debug)

《IDEA破解、配置、使用技巧与实战教程》系列文章目录 第一章 IDEA破解与HelloWorld的实战编写 第二章 IDEA的详细设置 第三章 IDEA的工程与模块管理 第四章 IDEA的常见代码模板的使用 第五章 IDEA中常用的快捷键 第六章 IDEA的断点调试&#xff08;Debug&#xff09; 第七章 …

基于chrome插件的企业应用

一、chrome插件技术介绍 1、chrome插件组件介绍 名称 职责 访问权限 DOM访问情况 popup 弹窗页面。即打开形式是通过点击在浏览器右上方的icon&#xff0c;一个弹窗的形式。 注: 展示维度 browser_action:所有页面 page_action:指定页面 可访问绝大部分api 不可以 bac…

数据分析入门:用Python和Numpy探索音乐流行趋势

一、引言 音乐是文化的重要组成部分&#xff0c;而音乐流行趋势则反映了社会文化的变迁和人们审美的变化。通过分析音乐榜单&#xff0c;我们可以了解哪些歌曲或歌手正在受到大众的欢迎&#xff0c;甚至预测未来的流行趋势。Python作为一种强大的编程语言&#xff0c;结合其丰…

【数据库系列】Parquet 文件介绍

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

记录些Spring+题集(8)

Spring Bean 的生命周期 Spring Bean 的生命周期涉及到 Spring 框架中对象的创建、初始化、使用和销毁等关键过程。 在Spring框架中&#xff0c;Bean的生命周期经历以下几个阶段&#xff1a; 1&#xff09;实例化&#xff1a; Spring 根据配置文件或注解等方式创建 Bean 实例…

《0基础》学习Python——第十八讲__爬虫\<1>

一、什么是爬虫 爬虫是一种网络数据抓取的技术。通过编写程序&#xff08;通常使用Python&#xff09;&#xff0c;爬虫可以自动化地访问网页&#xff0c;解析网页内容并提取出所需的数据。爬虫可以用于各种用途&#xff0c;如搜索引擎的索引&#xff0c;数据分析和挖掘&#x…

vue 腾讯云 javascript sdk + 简单富文本组件设计+实战

<template><div><quill-editor v-model"content" ref"myQuillEditor" :options"editorOption" change"onEditorChange"input"handleInput"></quill-editor><!-- 链接添加对话框 --><el-di…