【友元】

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

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

友元的关键字为 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. [转帖]gdb进阶调试技巧

    https://www.jianshu.com/p/9bdaa0644dba 整理一下在linux下C/C++用gdb工具debug一些提高效率的操作.基本的gdb操作就不在这里赘述了. 打印各种变量 ...

  2. [转帖]kubelet 原理解析三:runtime

    本文转自:https://feisky.xyz/posts/kube... 架构 Kubelet 架构图 Generic Runtime Manager:这是容器运行时的管理者,负责于 CRI 交互, ...

  3. Oracle 建立数据库dblink 然后同步部分表内容的总结

    同步处理部分数据 背景 最近在项目上发现两个分库进行数据同步时部分内容同步存在问题. 最简单的方法是导表,但是害怕有其他关联信息异常, 所以同事想到了dblink的方式. 这里简单整理一下 同事用到的 ...

  4. Go实现网络代理

    使用 Go 语言开发网络代理服务可以通过以下步骤完成.这里,我们将使用 golang.org/x/net/proxy 包来创建一个简单的 SOCKS5 代理服务作为示例. 步骤 1. 安装 golan ...

  5. 我为什么从Windows转到Linux?

    本文来自读者投稿! 大家好!我是 Guide 哥,Java 后端开发.一个会一点前端,喜欢烹饪的自由少年. 如果文章有任何需要改善和完善的地方,欢迎在评论区指出,共同进步! 喔,看到这个标题千万不要以 ...

  6. python入门之后须掌握的知识点(excel文件处理+邮件发送+实战:批量化发工资条)【二】

    相关文章: python处理Excel实现自动化办公教学(含实战)[一] python处理Excel实现自动化办公教学(含实战)[二] python处理Excel实现自动化办公教学(数据筛选.公式操作 ...

  7. 9.3 Windows驱动开发:内核解析PE结构节表

    在笔者上一篇文章<内核解析PE结构导出表>介绍了如何解析内存导出表结构,本章将继续延申实现解析PE结构的PE头,PE节表等数据,总体而言内核中解析PE结构与应用层没什么不同,在上一篇文章中 ...

  8. 4.5 C++ Boost 文件目录操作库

    Boost 库是一个由C/C++语言的开发者创建并更新维护的开源类库,其提供了许多功能强大的程序库和工具,用于开发高质量.可移植.高效的C应用程序.Boost库可以作为标准C库的后备,通常被称为准标准 ...

  9. powerDesigner 逆向工程 mysql 生成 PDM

     1. 信息补充说明 powerDesigner  16.5 mysql 5.6 主要内容:使用powerDesigner的逆向工程,将mysql中的数据库转换成PDM文件 所需资源: powerDe ...

  10. 英特尔发布酷睿Ultra移动处理器:Intel 4制程工艺、AI性能飙升

    英特尔今日发布了第一代酷睿Ultra移动处理器,是首款基于Intel 4制程工艺打造的处理器. 据了解,英特尔酷睿Ultra采用了英特尔首个用于客户端的片上AI加速器"神经网络处理单元(NP ...