【友元】

在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术

友元的目的就是让一个函数或者类 访问另一个类中私有成员

友元的关键字为 friend

友元的三种实现

  • 全局函数做友元
  • 类做友元
  • 成员函数做友元

全局函数友元

新建一个Building类,里面有客厅(public)和卧室(private)两个属性

class Building {

//行为
public:
//构造函数
Building() {
m_SittingRoom = "客厅";
m_BadRoom = "卧室";
} //属性
public:
string m_SittingRoom;
private:
string m_BadRoom;
}; int main() {
system("pause");
return 0;
}

在main外部(全局)创建一个函数goodGay,分别访问两个属性。

使用test01函数测试,当然私有属性要访问时会报错

class Building {

//行为
public:
//
Building() {
m_SittingRoom = "客厅";
m_BadRoom = "卧室";
} //属性
public:
string m_SittingRoom;
private:
string m_BadRoom;
}; void goodGay(Building *building) {
cout << "好基友正在访问: " << building->m_SittingRoom << endl;
//cout << "好基友正在访问: " << building->m_BedRoom << endl;
} void test01() {
Building building;
goodGay(&building);
} int main() { test01(); system("pause");
return 0;
}

这时,需要将void goodGay(Building *building)添加到Building类的开头,并以关键字‘friend’修饰

#include<iostream>
using namespace std;
#include<string> class Building { //声明友元
friend void goodGay(Building* building); //行为
public:
//
Building() {
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
} //属性
public:
string m_SittingRoom;
private:
string m_BedRoom;
}; void goodGay(Building *building) {
cout << "好基友正在访问: " << building->m_SittingRoom << endl;
cout << "好基友正在访问: " << building->m_BedRoom << endl;
} void test01() {
Building building;
goodGay(&building);
} int main() {
test01(); system("pause");
return 0;
}

由此,友元全局函数goodGay便可以访问Building类中的私有属性

类友元

例子的框架与之前类似

只是这次我们需要创建一个GoodGay类去访问

补充知识点:类外写成员函数

例如,现在有一个Building类

class Building
{
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;//卧室
}; int main(){ system("pause");
return 0;
}

该类中的构造函数(也是成员函数之一)只是声明还没有实现,我们可以在类外对其进行实现

class Building
{
public:
Building();
public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;//卧室
}; //类外实现成员函数
//"xxx :: xx函数",xxx表示声明了函数的作用域
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
} int main(){ system("pause");
return 0;
}

例子

根据上面的方法,我们在GoodGay类和Building类外面分别实现其构造函数

#include<iostream>
using namespace std;
#include<string> class Building;
class goodGay
{
public: goodGay();
void visit(); private:
Building *building;
}; class Building
{
//告诉编译器 goodGay类是Building类的好朋友,可以访问到Building类中私有内容
friend class goodGay; public:
Building(); public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;//卧室
}; //类外实现构造函数Building()
//作用域在Building类下
Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
} //类外实现goodGay构造函数
//作用域在goodGay类下
goodGay::goodGay()
{
//在堆区创建建筑物对象
//goodGay类中的Building *building指向该对象
building = new Building;
} //类外实现goodGay的成员函数
//作用域在goodGay类下
void goodGay::visit()
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;
cout << "好基友正在访问" << building->m_BedRoom << endl;
} void test01()
{
goodGay gg;
gg.visit(); } int main(){ test01(); system("pause");
return 0;
}

GoodGay类能访问Building类的私有属性的关键也是使用友元

即在Building类开头用‘friend’修饰

class Building
{
//告诉编译器 goodGay类是Building类的好朋友,可以访问到Building类中私有内容
friend class goodGay; public:
...

成员函数友元

例子

#include<iostream>
using namespace std;
#include<string> class Building;
class goodGay
{
public:
goodGay();
void visit(); //只让visit函数作为Building的好朋友,可以发访问Building中私有内容
void visit2(); private:
Building *building;
}; class Building
{
//告诉编译器 goodGay类中的visit成员函数 是Building好朋友,可以访问私有内容
friend void goodGay::visit(); public:
Building(); public:
string m_SittingRoom; //客厅
private:
string m_BedRoom;//卧室
}; //类外实现构造函数Building()
//作用域在Building类下
Building::Building()
{
this->m_SittingRoom = "客厅";
this->m_BedRoom = "卧室";
} //类外实现构造函数goodGay()
//作用域在goodGay类下
goodGay::goodGay()
{
building = new Building;
} //类外实现成员函数visit()
//作用域在goodGay类下
void goodGay::visit()
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;
cout << "好基友正在访问" << building->m_BedRoom << endl;
} //类外实现成员函数visit2()
//作用域在goodGay类下
void goodGay::visit2()
{
cout << "好基友正在访问" << building->m_SittingRoom << endl;
//cout << "好基友正在访问" << building->m_BedRoom << endl;
} void test01()
{
goodGay gg;
gg.visit();
} int main(){
test01(); system("pause");
return 0;
}

技巧

如果之后要用到某个类,但是该类的细节还没有写,可以先写个占位的代码

class Building;
class goodGay{
public:
goodGay();
void visit(); //只让visit函数作为Building的好朋友,可以发访问Building中私有内容
void visit2(); private:
//用到了但还没写
Building *building;
}; ...
//之后再定义
class Building{ }

【C++ OOP 03 友元】各种友元例子以及如何类外写成员函数的更多相关文章

  1. c++友元函数、友元类、友成员函数

    友元函数:不是类成员函数,是一个类外的函数,但是可以访问类所有成员. class Point{ public: friend void fun(Point t);//友元函数 private: int ...

  2. C++ 友元(friend关键字)、类中的重载、操作符重载(operator关键字)

    C++ 中友元的用法: 1.在类中使用friend关键字声明 2.类的友元可以是其它类或者具体函数 3.友元不是类的一部分 4.友元不受类中访问级别的限制 5.友元可以直接访问具体类中的所有成员. 友 ...

  3. 友元(友元函数、友元类和友元成员函数) C++

    有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,这是很方便做到的.例如被重载的操作符,如输入或输出操作符,经常需要访问类的私有数据成员. 友元(frend)机制允许一个类将 ...

  4. C++友元(友元函数、友元类和友元成员函数)

    友元(友元函数.友元类和友元成员函数) C++ 有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,这是很方便做到的.例如被重载的操作符,如输入或输出操作符,经常需要访问类的私 ...

  5. C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 对运算符重载的函数有两种处理方式:(1)把运算符 ...

  6. C++ 友元 (全局函数做友元) (类做友元) (成员函数做友元)

    1 //友元 全局函数做友元 2 /* 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 ...

  7. C++基础-4-封装(构造函数与析构函数,深拷贝与浅拷贝,静态成员,this,友元,const修饰成员函数)

    4. 封装 4.1.1 封装的意义 1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 con ...

  8. 读书笔记 effective c++ Item 23 宁可使用非成员非友元函数函数也不使用成员函数

    1. 非成员非友元好还是成员函数好? 想象一个表示web浏览器的类.这样一个类提供了清除下载缓存,清除URL访问历史,从系统中移除所有cookies等接口: class WebBrowser { pu ...

  9. C++运算符重载三种形式(成员函数,友元函数,普通函数)详解

    首先,介绍三种重载方式: //作为成员函数重载(常见) class Person{ Private: string name; int age; public: Person(const char* ...

  10. 重载运算符:类成员函数or友元函数

    类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(co ...

随机推荐

  1. Redis labs 的安装

    Install and setup This guide shows how to install Redis Enterprise Software, which includes several ...

  2. Opentelemetry Collector的配置和使用

    Collector的配置和使用 目录 Collector的配置和使用 Collector配置 Receivers Processors Exporters Service Extensions 使用环 ...

  3. js中for in和for of详细讲解

    for in的详细讲解, for in遍历数组的毛病 1.index索引为字符串型数字,不能直接进行几何运算. 2.遍历顺序有可能不是按照实际数组的内部顺序 3.使用for in会遍历数组[所有的可枚 ...

  4. 理解Vuex的辅助函数mapState

    参考的地址是: https://www.cnblogs.com/tugenhua0707/p/9794423.html 之所以会在这里记录下来,是为了方便自己以后忘记的时候查看学习而已~: 并没有别的 ...

  5. TienChin-系统功能介绍

    线索管理 添加线索 查看线索 删除线索 修改线索 分配线索: ​将录入到系统的线索,分配给某一个市场专员去处理 跟进线索: ​持续跟进一条线索 1.判断是否伪线索 2.持续跟进,每次跟进需要有记录 3 ...

  6. Python 调用Zoomeye搜索接口

    钟馗之眼是一个强大的搜索引擎,不同于百度谷歌,它主要收集网络中的主机,服务等信息,国内互联网安全厂商知道创宇开放了他们的海量数据库,对之前沉淀的数据进行了整合.整理,打造了一个名符其实的网络空间搜索引 ...

  7. GDB调试程序 [补档-2023-07-19]

    gdb调试 ​ 它是gcc的调试工具,调试工具都能干什么就不多说了. 7-1生成调试信息 ​ 在使用gcc编译c/c++的程序时,需要在编译命令中加入 -g 这一参数,它可以为你显示函数名,变量名 等 ...

  8. ClickHouse(24)ClickHouse集成mongodb表引擎详细解析

    目录 MongoDB 创建一张表 用法示例 资料分享 系列文章 clickhouse系列文章 MongoDB MongoDB 引擎是只读表引擎,允许从远程 MongoDB 集合中读取数据(SELECT ...

  9. 关于TypeScript中提示xxx is declared but its value is never read的解决方法

    首先,提示很明显,是定义了变量,但是却没有使用.解决方案有如下两种: 一: 需要确定变量是否真的没有使用到,如果没有使用直接删除即可. 二: 对于方法中的入参,是没法随便删除的.这时候我们可以利用Ty ...

  10. ABC306 A - F

    ABC306 A - F 代码不提供 A 题意:吧字符串的每个字符连续输出两遍,记得不要快读,不要忘记输入 $ n $ 纪念 Qinzh A 题 WA 掉 B 题意:给定长度为 $ 64 $ 的数组 ...