C++友元friend --c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作

本文主要是介绍C++友元friend --c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

通常对于普通函数来说,要访问类的保护成员是不可能的,如果想这么做那么必须把类的成员都生命成为public(共用的),然而这做带来的问题遍是任何外部函数都可以毫无约束的访问它操作它,c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作避免把类成员全部设置成public,最大限度的保护数据成员的安全。 

   友元能够使得普通函数直接访问类的保护数据,避免了类成员函数的频繁调用,可以节约处理器开销,提高程序的效率,但矛盾的是,即使是最大限度的保护,同样也破坏了类的封装特性,这即是友元的缺点,在现在cpu速度越来越快的今天我们并不推荐使用它,但它作为c++一个必要的知识点,一个完整的组成部分,我们还是需要讨论一下的。 

 

1. 在类里声明一个普通函数,在前面加上friend修饰,那么这个函数就成了该类的友元,可以访问该类的一切成员。 

   下面我们来看一段代码,看看我们是如何利用友元来访问类的一切成员的。

#include <iostream>    
using namespace std;  
class Internet    
{    
public:    
    Internet(char *name,char *address)    
    {    
        strcpy(Internet::name,name);    
        strcpy(Internet::address,address);     
    }  
friend void ShowN(Internet &obj);//友元函数的声明  
public:    
    char name[20];  
    char address[20];  
};  
  
  
void ShowN(Internet &obj)//函数定义,不能写成,void Internet::ShowN(Internet &obj)  
{  
    cout<<obj.name<<endl;  
}  
void main()    
{  
    Internet a("中国软件开发实验室","www.cndev-lab.com");  
    ShowN(a);  
    cin.get();  
}

  上面的代码通过友元函数的定义,我们成功的访问到了a对象的保护成员name,友元函数并不能看做是类的成员函数,它只是个被声明为类友元的普通函数,所以在类外部函数的定义部分不能够写成void Internet::ShowN(Internet &obj),这一点要注意。

  

2. 一个普通函数可以是多个类的友元函数,对上面的代码我们进行修改,注意观察变化:

#include <iostream>    
using namespace std;  
class Country;  
class Internet    
{    
public:    
    Internet(char *name,char *address)    
    {    
        strcpy(Internet::name,name);    
        strcpy(Internet::address,address);     
    }  
friend void ShowN(Internet &obj,Country &cn);//注意这里  
public:    
    char name[20];  
    char address[20];  
};  
  
class Country  
{  
public:  
    Country()  
    {  
        strcpy(cname,"中国");  
    }  
friend void ShowN(Internet &obj,Country &cn);//注意这里  
protected:  
    char cname[30];  
};  
  
void ShowN(Internet &obj,Country &cn)  
{  
    cout<<cn.cname<<"|"<<obj.name<<endl;  
}  
void main()    
{  
    Internet a("中国软件开发实验室","www.cndev-lab.com");  
    Country b;  
    ShowN(a,b);  
    cin.get();  
}

 

3一个类的成员函数函数也可以是另一个类的友元从而可以使得一个类的成员函数可以操作另一个类的数据成员,我们在下面的代码中增加一类Country,注意观察:

#include <iostream>    
using namespace std;  
class Internet;  
  
class Country  
{  
public:  
    Country()  
    {  
        strcpy(cname,"中国");  
    }  
    void Editurl(Internet &temp);//成员函数的声明  
protected:  
    char cname[30];  
};  
class Internet  
{    
public:    
    Internet(char *name,char *address)    
    {    
        strcpy(Internet::name,name);    
        strcpy(Internet::address,address);   
    }  
    friend void Country::Editurl(Internet &temp);//友元函数的声明  
protected:    
    char name[20];  
    char address[20];  
};  
void Country::Editurl(Internet &temp)//成员函数的外部定义  
{  
    strcpy(temp.address,"edu.cndev-lab.com");  
    cout<<temp.name<<"|"<<temp.address<<endl;  
}  
void main()  
{  
    Internet a("中国软件开发实验室","www.cndev-lab.com");  
    Country b;  
    b.Editurl(a);  
    cin.get();  
}

 

4.整个类也可以是另一个类的友元,该友元也可以称做为友类。友类的每个成员函数都可以访问另一个类的所有成员。 
  示例代码如下:

#include <iostream>    
using namespace std;  
class Internet;  
  
class Country  
{  
public:  
    Country()  
    {  
        strcpy(cname,"中国");  
    }  
    friend class Internet;//友类的声明  
protected:  
    char cname[30];  
};  
class Internet  
{  
public:    
    Internet(char *name,char *address)    
    {    
        strcpy(Internet::name,name);    
        strcpy(Internet::address,address);   
    }  
    void Editcname(Country &temp);  
protected:    
    char name[20];  
    char address[20];  
};  
void Internet::Editcname(Country &temp)  
{  
    strcpy(temp.cname,"中华人民共和国");   
}  
void main()  
{  
    Internet a("中国软件开发实验室","www.cndev-lab.com");  
    Country b;  
    a.Editcname(b);  
    cin.get();  
}

  在上面的代码中我们成功的通过Internet类Editcname成员函数操作了Country类的保护成员cname。 

   在编程中,我们使用友元的另外一个重要原因是为了方便重载操作符的使用,这些内容我们将在后面的教程着重讨论!

这篇关于C++友元friend --c++利用friend修饰符,可以让一些你设定的函数能够对这些保护数据进行操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Ubuntu 24.04启用root图形登录的操作流程

《Ubuntu24.04启用root图形登录的操作流程》Ubuntu默认禁用root账户的图形与SSH登录,这是为了安全,但在某些场景你可能需要直接用root登录GNOME桌面,本文以Ubuntu2... 目录一、前言二、准备工作三、设置 root 密码四、启用图形界面 root 登录1. 修改 GDM 配

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

C++中全局变量和局部变量的区别

《C++中全局变量和局部变量的区别》本文主要介绍了C++中全局变量和局部变量的区别,全局变量和局部变量在作用域和生命周期上有显著的区别,下面就来介绍一下,感兴趣的可以了解一下... 目录一、全局变量定义生命周期存储位置代码示例输出二、局部变量定义生命周期存储位置代码示例输出三、全局变量和局部变量的区别作用域

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

MySql基本查询之表的增删查改+聚合函数案例详解

《MySql基本查询之表的增删查改+聚合函数案例详解》本文详解SQL的CURD操作INSERT用于数据插入(单行/多行及冲突处理),SELECT实现数据检索(列选择、条件过滤、排序分页),UPDATE... 目录一、Create1.1 单行数据 + 全列插入1.2 多行数据 + 指定列插入1.3 插入否则更

MySQL深分页进行性能优化的常见方法

《MySQL深分页进行性能优化的常见方法》在Web应用中,分页查询是数据库操作中的常见需求,然而,在面对大型数据集时,深分页(deeppagination)却成为了性能优化的一个挑战,在本文中,我们将... 目录引言:深分页,真的只是“翻页慢”那么简单吗?一、背景介绍二、深分页的性能问题三、业务场景分析四、

JSONArray在Java中的应用操作实例

《JSONArray在Java中的应用操作实例》JSONArray是org.json库用于处理JSON数组的类,可将Java对象(Map/List)转换为JSON格式,提供增删改查等操作,适用于前后端... 目录1. jsONArray定义与功能1.1 JSONArray概念阐释1.1.1 什么是JSONA

PostgreSQL中rank()窗口函数实用指南与示例

《PostgreSQL中rank()窗口函数实用指南与示例》在数据分析和数据库管理中,经常需要对数据进行排名操作,PostgreSQL提供了强大的窗口函数rank(),可以方便地对结果集中的行进行排名... 目录一、rank()函数简介二、基础示例:部门内员工薪资排名示例数据排名查询三、高级应用示例1. 每

全面掌握 SQL 中的 DATEDIFF函数及用法最佳实践

《全面掌握SQL中的DATEDIFF函数及用法最佳实践》本文解析DATEDIFF在不同数据库中的差异,强调其边界计算原理,探讨应用场景及陷阱,推荐根据需求选择TIMESTAMPDIFF或inte... 目录1. 核心概念:DATEDIFF 究竟在计算什么?2. 主流数据库中的 DATEDIFF 实现2.1

SpringBoot结合Docker进行容器化处理指南

《SpringBoot结合Docker进行容器化处理指南》在当今快速发展的软件工程领域,SpringBoot和Docker已经成为现代Java开发者的必备工具,本文将深入讲解如何将一个SpringBo... 目录前言一、为什么选择 Spring Bootjavascript + docker1. 快速部署与