友元成员函数使用时的注意事项

2023-11-18

友元成员函数的注意事项

友元的概念

“友元”的概念其实是针对于类的私有成员来说的,一个类的由于封装的缘故,类体中私有成员是不可以被外界访问的,无论是继承也好,都是无法访问类内私有成员的。但是正是有那么一些人,愿意打破陈规破例访问类体内的私有成员,此时“友元”的概念闪亮登场。其实我们的普通函数是可以访问类体中的public,但是自从来了“友元”,protected和private类型的变量都被尽收眼底,无处可藏。

友元成员函数中的注意事项

友元成员函数声明和定义的顺序必须满足一定要求,否则VS2017会报错。

#include <iostream>  
#include <string>  
using namespace std;  
  
class Person;  
class Student  
{  
public:  
    void ShowInf(Person& PersonObject);  
};  
  
class Person  
{  
    friend void Student::ShowInf(Person& PersonObject);  
private:  
    int age;  
    string name;  
public:  
    Person(string name, int age)  
    {  
        this->name = name;  
        this->age = age;  
    }  
    Person(Person& PersonObject)  
    {  
        this->name = PersonObject.name;  
        this->age = PersonObject.age;  
    }  
    Person operator = (Person PersonObject)  
    {  
        this->age = PersonObject.age;  
        this->name = PersonObject.name;  
    }  
};  
  
void Student::ShowInf(Person& PersonObject)  
{  
    cout << PersonObject.name << "的年龄为" << PersonObject.age << endl;  
}  
  
int main()  
{  
    Person PersonObject("张三", 19);  
    Student StudentObject;  
    StudentObject.ShowInf(PersonObject);  
}  

 

我们这里用Student类中的ShowInf()成员函数访问Person类中的私有成员name和age。

① 首先,我们先声明可以下Person类类型,这样我们才可以在下面定义Student类使用这个数据类型,但是一定要注意,此时的Person类是个空类只是个声明我任何实际成员参数,因此我们Student中的ShowInf()要在Person类定义完后在进行定义,此时我们才可以在Student中的ShowInf()中访问Person类中的成员,这里我们先给Student中的ShowInf()函数一个类内声明;

② 定义Person类的实体,在定义Person类实体之前,千万不要定义Student中的ShowInf()函数,因为Person类实体未定义之前我们也不知道Person类中有什么成员;

③ 定义Student类中可以访问呢Person类私有成员的函数实体,此时定义实体才有意义,编译器才不会报错,因为,这个时候Person类内有啥已经知道了,访问Person类中的成员也就顺理成章了。

④ 特别注意:这里我们只能通过向函数传递形参来访问Person类中的私有成员,因为在Person实体未定义之前,编译器是不允许我们定义Person类的对象的。

错误示例

#include <iostream>  
#include <string>  
using namespace std;  
  
class Person;  
class Student  
{  
private:  
        Person PersonObject;  
public:  
    void ShowInf();  
        Student(Person PersonObject)  
        {  
            this->PersonObject = PersonObject;  
        }  
};  
  
class Person  
{  
    friend void Student::ShowInf();  
private:  
    int age;  
    string name;  
public:  
    Person(string name, int age)  
    {  
        this->name = name;  
        this->age = age;  
    }  
    Person(Person& PersonObject)  
    {  
        this->name = PersonObject.name;  
        this->age = PersonObject.age;  
    }  
    Person operator = (Person PersonObject)  
    {  
        this->age = PersonObject.age;  
        this->name = PersonObject.name;  
    }  
};  
  
void Student::ShowInf()  
{  
    cout << PersonObject.name << "的年龄为" << PersonObject.age << endl;  
}  
  
int main()  
{  
    Person PersonObject("张三", 19);  
    Student StudentObject(PersonObject);  
    StudentObject.ShowInf();  
}  

 

这里,我们在未定义Person实体之前(仅仅定义了一个Person类的声明)就在Student类体内定义Person类的成员函数,这样的话编译器并不知道给Person类对象分配多少内存空间,因此此时编译器会报错!

我们一定要注意:在未定义的类实体之前,一定不要贸然的在其他类体内定义该类类型的对象作为成员变量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

友元成员函数使用时的注意事项 的相关文章

  • scala案例类问题

    我有两个关于 案例类的问题 可以用作 case head tail gt 它是如何工作的 意思是 Scala 用于将 List 实例与 case 类进行匹配的流程到底是什么 鉴于我有一个类 MyClass 带有运算符 op 我可以创建一个名
  • 访问模型字段内的模型实例

    我有一个模型 事件 它具有用户模型 事件的所有者 的外键 该用户可以使用以下 ManyToManyField 邀请其他用户 invites models ManyToManyField User related name invited u
  • 使用嵌套 C++ 类和枚举的优点和缺点?

    使用嵌套公共 C 类和枚举的优点和缺点是什么 例如 假设您有一个名为printer 并且此类还存储输出托盘上的信息 您可以 class printer public std string name enum TYPE TYPE LOCAL
  • 带参数和不带参数的 super() 有什么区别?

    我遇到了一个使用的代码super 方法有两种不同的方式 我不明白逻辑上有什么区别 我现在正在学习pygame模块 我有一个任务来创建一个类Ball它继承自Sprite这是一个来自pygame模块 如果我没记错的话 我遇到了这段代码 impo
  • 作为属性的自定义类的数组

    我试图使用自定义类的数组作为我的组件的属性 但问题是这些值没有保存到组件中 这意味着如果我设置值 保存所有内容并再次打开项目 组件的值消失 我的代码如下所示 unit Unit1 interface uses Windows ExtCtrl
  • C# 中类实例的内存使用情况[重复]

    这个问题在这里已经有答案了 可能的重复 C NET 对象使用多少内存 https stackoverflow com questions 426396 how much memory does a c net object use 就像标题
  • Moq-ing 类或接口有什么区别?

    我一直在使用moq http code google com p moq 在我的单元测试中模拟对象 我在关于最小起订量的网站上看到它能够模拟类和接口 有一天 我与我的一位同事进行了讨论 他们表示没有理由模拟类 我应该只模拟接口 我对此并没有
  • 如何在 Windows 上使用 Pyreverse

    我想使用pyreverse 创建图表类 我下载它 当我使用这个命令时 pyreverse bat c PyreverseCommand a1 s1 f ALL o png test py 我收到错误 名称 点 无法识别 什么是 点 如何创建
  • Haskell 中的异构多态性(正确方法)

    让一个模块来抽象Area操作 错误的定义 class Area someShapeType where area someShapeType gt Float module utilities sumAreas Area someShape
  • 如何动态构造方法?

    我设计了一个类 它非常标准 具有一些方法属性 class foo def f1 self print f1 def f2 self print f2 def fn self print fn 现在我想创建一个包含一组 foo 实例的类 cl
  • Ruby 中@@ 和@ 有什么区别? [复制]

    这个问题在这里已经有答案了 我刚刚开始学习 Ruby 一直无法找到关于 和 在类变量方面的区别的很好的解释 如果有人可以提供一个基本的直观示例 那就太好了 另外它们可以互换吗 前缀为的变量 是一个类变量 前缀为 是一个实例变量 在这个答案中
  • 在 init 之外在 java 中创建对象

    因此 对于我正在创建的游戏 我有一些扩展 GameDriver 的类 到目前为止 在所有其他类上我都能够扩展 GameDriver 然后在 GameDriver 中我可以执行以下操作 ArrayList
  • 在 Delphi XE 中将类作为过程的参数传递

    我需要做的是这样的 procedure A type of form var form TForm begin form type of form Create application form showmodal freeandnil f
  • 从 python 中的类调用函数 - 不同的方式

    EDIT2 谢谢大家的帮助 编辑 添加 staticmethod后 它可以工作 但是我仍然想知道为什么我在这里遇到类型错误 我刚刚开始使用 OOPS 并且对它完全陌生 我有一个非常基本的问题 关于从类中调用函数的不同方式 我有一个 test
  • ECMAScript 6 类中的 getter 和 setter 有何用途?

    我对 ECMAScript 6 类中 getter 和 setter 的意义感到困惑 什么目的 下面是我参考的一个例子 class Employee constructor name this name name doWork return
  • 从模板类创建对象时出错

    我一直在尝试找到一种方法 从 C 中的多元正态分布中采样随机向量 同时具有均值向量和协方差矩阵 就像 Matlab 的那样mvnrnd功能有效 我找到了实现此功能的类的相关代码这一页 http lost found wandering bl
  • 参考接口创建对象

    引用变量可以声明为类类型或接口类型 如果变量声明为接口类型 则它可以引用实现该接口的任何类的任何对象 根据上面的说法我做了一个理解上的代码 正如上面所说声明为接口类型 它可以引用实现该接口的任何类的任何对象 但在我的代码中显示display
  • AppDelegate 的变量用作全局变量不起作用

    我想使用我的 AppDelegate 来存储任何其他类都可以访问的对象 我已经像这样声明了这个 AppDelegate interface MyAppDelegate UIResponder
  • 检查一个类是否是另一个类的子类

    我想在不创建实例的情况下检查一个类是否是另一个类的子类 我有一个类 它接收类名作为参数 作为验证过程的一部分 我想检查它是否属于特定的类系列 以防止安全问题等 有什么好的方法可以做到这一点吗 is subclass of http php
  • 用于多个窗口的 Tkinter 示例代码,为什么按钮无法正确加载?

    我正在编写一个程序 应该 按一下按钮即可打开一个窗口 按另一个按钮关闭新打开的窗口 我使用类 以便稍后可以将代码插入到更大的程序中 但是 我无法正确加载按钮 import tkinter as tk class Demo1 tk Frame

随机推荐

  • git命令全家福

    1 切换分支 git checkout dev 2 拉取远程分支到本地 并切换到该分支 git pull git checkout b dev 本地分支名称 origin dev 远程分支名称 3 查看分支 git branch a
  • 2018年最常见的Python面试题&答案(上篇)

    Q 1 Python有哪些特点和优点 作为一门编程入门语言 Python主要有以下特点和优点 可解释 具有动态特性 面向对象 简明简单 开源 具有强大的社区支持 当然 实际上Python的优点远不止如此 可以阅读该文档 详细了解 https
  • ubuntu安装svn服务器

    安装命令 sudo apt getinstall subversion 创建项目目录 sudo mkdir home svn cd home svn project sudo chmod R777 project 创建svn仓库 sudo
  • rbac 另外一种逃逸

    Privilege Escalation from Node Proxy Rights in Kubernetes RBAC aquasec com
  • mysql时间相减-时间运算-转换毫秒值的问题

    mysql时间运算 一 时间相减发现与结果差距很大 二 原因 三 正确的运算 一 时间相减发现与结果差距很大 mysql gt select t1 t2 t2 t1 from mytest t1 t2 t2 t1 2013 04 21 16
  • Spring4学习笔记:Spring框架中为一个bean配置依赖注入的方式

    Spring框架为一个bean配置依赖注入的四种方式 属性注入 构造方法注入 工厂注入 泛型依赖注入 1 属性注入 属性方法注入利用setXxx 方法注入 Bean 的属性值或者依赖对象 由于属性注入方式具有可选择性和灵活性高的优点 因此属
  • 【算法】深度优先搜索DFS 入门:基本知识+经典例题

    DFS最重要的是理清搜索顺序 ps 这是我入门dfs时写的博客 后来dfs渐渐熟练了 也补充了一些题目上去 带原题和代码 个人感觉整篇博文从上到下确实由易到难 代码也由开始的冗长变得渐渐精简 自学DFS看的视频 小甲鱼 讲原理 青岛大学 王
  • Linux / pthread_create() 函数所使用的线程函数为什么必须是静态函数?

    答案 因为 pthread create 函数要求的线程函数必须满足如下格式 void ThreadFunc void args 对于普通类成员函数 虚函数 他们实际上都是包含了调用他们的对象的 this 指针 即 经过编译器优化 线程函数
  • 【华为OD机试真题】对称字符串(C++&java&python)100%通过率 超详细代码注释 代码解读

    华为OD机试真题 2022 2023 真题目录 点这里 华为OD机试真题 信号发射和接收 试读 点这里 华为OD机试真题 租车骑绿道 试读 点这里 对称字符串 时间限制 1s空间限制 256MB限定语言 不限 题目描述 对称就是最大的美学
  • Period 【HDU - 1358】【KMP求周期】

    学习KMP算法可以参阅这篇文章 不懂的可以在线回答 题目链接 题意 我们想知道一串字符中的前缀中有多少最大周期数 例如 aaa 中 前两个 aa 最小周期长度为 a 所以周期长度为2 前三个 aaa 的最小周期也是 a 所以周期长度为3 再
  • 景深概念、计算方法与影响因素

    一 景深概念 景深 Depth of Field DOF 是指在摄影机镜头或其他成像器前沿能够取得清晰图像的成像所测定的被摄物体前后距离范围 而光圈 镜头 及拍摄物的距离是影响景深的重要因素 在聚焦完成后 焦点前后的范围内所呈现的清晰图像
  • caffe cudnn出现错误: declaration is incompatible with "const char *cudnnGetErrorString(cudnnStatus_t)"

    cudnn h中 inline const char cudnnGetErrorString cudnnStatus t status 修改为 inline const char CUDNNWINAPI cudnnGetErrorStrin
  • wallpaper Engine 安装教程

    今天在网上看到了一个软件wallpaper Engine 效果太酷炫了 就买了个来试试 效果是很棒 但是缺点是无法和桌面管理工具兼容 例如Fences 如果要二者兼得 则必须要PS辅助 运行环境 Windows7 Wallpaper Eng
  • GeckoDriver 国内镜像源加速下载

    GeckoDriver 国内镜像源加速下载 https mirrors huaweicloud com geckodriver
  • FastAPI从入门到实战(4)——路径参数与数值校验

    简单记录路径参数的类型 错误检查 自动填充 数据转换 解析 验证 包括数字大小范围的验证 参数别名 API 交互文档中传参演示等内容 一个伪静态请求 app01 get stu01 parameters def path params01
  • 模拟电子技术

    模电 半导体器件 二极管 1 半导体的基础知识 2 半导体二极管 场效应管三极管及其放大电路 1 绝缘栅型场效应管 MOSFET 2 结型场效应管 JFET 3 场效应管的主要参数 场效应管 放大电路 基本放大电路 差分式放大电路 集成运算
  • vue3 + gzip +nginx 部署 静态文件被识别成text/html的问题

    Failed to load module script Expected a JavaScript module script but the server responded with a MIME type of text html
  • java:面向对象(多态的主板示例)。

    需求 电脑运行实例 电脑运行基于主板 我们写这样一个代码 class MainBoard public void run System out println mainboard run class DuoTaiDemo4 public s
  • 玩转格式转换——.xml->.txt

    一个帅气的boy 你可以叫我 loVe 个人主页 l Ve的个人主页 如果对你有帮助的话希望三连 支持一下博主 VOC数据集转YOLO数据集 1 前言 2 分析xml txt数据 3 转换过程 4 最后结果对比 1 前言 最近学习Yolo
  • 友元成员函数使用时的注意事项

    友元成员函数的注意事项 友元的概念 友元 的概念其实是针对于类的私有成员来说的 一个类的由于封装的缘故 类体中私有成员是不可以被外界访问的 无论是继承也好 都是无法访问类内私有成员的 但是正是有那么一些人 愿意打破陈规破例访问类体内的私有成