【友元】

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

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

友元的关键字为 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. 我们开源了一个轻量的 Web IDE UI 框架

    我们开源了一个轻量的 Web IDE UI 框架 Molecule 一个轻量的 Web IDE UI 框架 简介 Molecule 是一个受 VS Code 启发,使用 React.js 构建的 We ...

  2. 高性能MySQL实战(二):索引 | 京东物流技术团队

    我们在上篇 高性能MySQL实战(一):表结构 中已经建立好了表结构,这篇我们则是针对已有的表结构和搜索条件为表创建索引. 1. 根据搜索条件创建索引 我们还是先将表结构的初始化 SQL 拿过来: C ...

  3. node借助jsonwebtoken生成token以及验证token是否过期

    生成token使用 jsonwebtoken 插件 我当时使用的版本"jsonwebtoken": "^9.0.0", cnpm i jsonwebtoken ...

  4. consul系列文章01---docker安装consul

    1.下载镜像 2.运行容器 docker run --name consul -d -p 8500:8500 --restart=always  consul agent -server -boots ...

  5. Flask 框架实现自定义分页

    手撸的表格分页: Flask框架下的分页,我研究了很久,自带的分页方法不稳定,还不如自己手撸的好使. <!--name:ndex.html--> <!DOCTYPE html> ...

  6. layui表格中关键字加粗加红显示

    使layui表格中根据关键词进行加红加粗显示,先看效果 前台代码 <script tab="table处理及事件"> var table = layui.table; ...

  7. webpack与其常见loader加载器使用方式

    webpack是什么 webpack是前端项目工程化的具体解决方案. 主要功能:提供了友好的前端模块化开发支持,支持代码压缩混淆(去除空格和注释,让文件体积更小),处理浏览器端JS的兼容性(将箭头函数 ...

  8. 顶配涨至近2万 该买还是买!iPhone15正面曝光 与历代苹果手机对比边框爆窄

    从曝光的iPhone 15正面渲染图来看,其颜值确实要比上代又提高不少. 外媒放出了一组iPhone 15 Pro的正面渲染图照,从图片看边框非常的窄,与历代iPhone 边框对比,这个特点更是被放大 ...

  9. Vulkan学习苦旅02:看不见的窗口(创建VkInstance与VkSurfaceKHR)

    在上一节中,我们搭建了学习Vulkan所需的环境.今天,我们将会初步了解"地图"顶层的内容.  如图所示,"地图"的顶层有两个模块: Instance和Surf ...

  10. AutoGPT是什么?超简单安装使用教程

    1.AutoGPT 最近几天当红炸子鸡的是AutoGPT,不得不说AI发展真快啊,几天出来一个新东西,都跟不上时代的脚步了. AutoGPT是一个开源的应用程序,展示了GPT-4语言模型的能力.这个程 ...