【C++ OOP 03 友元】各种友元例子以及如何类外写成员函数
【友元】
在程序里,有些私有属性 也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术
友元的目的就是让一个函数或者类 访问另一个类中私有成员
友元的关键字为 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 友元】各种友元例子以及如何类外写成员函数的更多相关文章
- c++友元函数、友元类、友成员函数
友元函数:不是类成员函数,是一个类外的函数,但是可以访问类所有成员. class Point{ public: friend void fun(Point t);//友元函数 private: int ...
- C++ 友元(friend关键字)、类中的重载、操作符重载(operator关键字)
C++ 中友元的用法: 1.在类中使用friend关键字声明 2.类的友元可以是其它类或者具体函数 3.友元不是类的一部分 4.友元不受类中访问级别的限制 5.友元可以直接访问具体类中的所有成员. 友 ...
- 友元(友元函数、友元类和友元成员函数) C++
有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,这是很方便做到的.例如被重载的操作符,如输入或输出操作符,经常需要访问类的私有数据成员. 友元(frend)机制允许一个类将 ...
- C++友元(友元函数、友元类和友元成员函数)
友元(友元函数.友元类和友元成员函数) C++ 有些情况下,允许特定的非成员函数访问一个类的私有成员,同时仍阻止一般的访问,这是很方便做到的.例如被重载的操作符,如输入或输出操作符,经常需要访问类的私 ...
- C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数
(根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 对运算符重载的函数有两种处理方式:(1)把运算符 ...
- C++ 友元 (全局函数做友元) (类做友元) (成员函数做友元)
1 //友元 全局函数做友元 2 /* 3 #include <iostream> 4 #include <string> 5 using namespace std; 6 7 ...
- C++基础-4-封装(构造函数与析构函数,深拷贝与浅拷贝,静态成员,this,友元,const修饰成员函数)
4. 封装 4.1.1 封装的意义 1 #include<iostream> 2 #include<string> 3 using namespace std; 4 5 con ...
- 读书笔记 effective c++ Item 23 宁可使用非成员非友元函数函数也不使用成员函数
1. 非成员非友元好还是成员函数好? 想象一个表示web浏览器的类.这样一个类提供了清除下载缓存,清除URL访问历史,从系统中移除所有cookies等接口: class WebBrowser { pu ...
- C++运算符重载三种形式(成员函数,友元函数,普通函数)详解
首先,介绍三种重载方式: //作为成员函数重载(常见) class Person{ Private: string name; int age; public: Person(const char* ...
- 重载运算符:类成员函数or友元函数
类成员函数: bool operator ==(const point &a)const { return x==a.x; } 友元函数: friend bool operator ==(co ...
随机推荐
- [转帖]spec2017 安装和使用
https://zhuanlan.zhihu.com/p/534205632 SPEC成立于1988年,SPEC基准广泛用于评估计算机系统的性能.SPEC CPU套件通过测量几个程序(例如编译器GCC ...
- [转帖]OutOfMemoryError内存溢出相关的JVM参数
原文在这里: OutOfMemoryError内存溢出相关的JVM参数 JVM提供了很多处理内存溢出的相关参数,本文主要来讲解下这些参数,当你遇到内存溢出的时候可能会对你非常有帮助,这些参数主要有: ...
- java -D的一些学习和使用
背景 java开发的程序有很多进行配置的方式 可以通过 yaml文件或者是xml文件 也可以通过环境变量的方式. 1. 容器的话可以使用 -e 或者是env进行注入 2. K8S的话可以通过 conf ...
- 银河麒麟安装LLDB的方法以及调试 dump 文件 (未完成)
今天同事要进行 lldb进行调试dotnet的bug 本来在x86 上面进行相应的处理 但是发现报错. 没办法 正好有一台借来的arm服务器就搞了一下. 简单记录一下安装方法 1. 安装 apt的so ...
- Redis7.0 编译安装以及简单创建Cluster测试服务器的方法
背景 北京时间2022.4.27 晚上九点半左右, Redis 7.0.0 已经GA. 为了进行简单的学习, 这边进行了简单验证工作. 本次主要分为编译, 测试集群搭建,以及springboot进行简 ...
- 一文搞懂Redis
作者: 京东物流 刘丽侠 姚再毅 康睿 刘斌 李振 一.Redis的特性 1.1 Redis为什么快? 基于内存操作,操作不需要跟磁盘交互,单次执行很快 命令执行是单线程,因为是基于内存操作,单次执行 ...
- TypeScript中Never类型和类型断言
Never 类型 never类型表示:那些永不存在的值的类型. 例如:never类型是那些总是会[抛出异常]或根本就[不会有返回值的函数表达式]或[箭头函数表达式的返回值类型] never类型是任何类 ...
- 【踩坑记录】SpringBoot跨域配置不生效
问题复现: 明明在拦截器里配置了跨域,就是不生效,使用PostMan等后端调试工具调试,均正常,Response中有Access-Control-Allow-Origin: *,这个Header,但是 ...
- C/C++ 常用加解密算法收集
网上收集的一些开发常用的加密解密算法的使用技巧,第三方库 Crypto++ 也可实现 Base64加密1 base64.h #ifndef base64_h #define base64_h #inc ...
- MySQL 数据库读写分离
MySQL 是最流行的关系型数据库管理系统,MySQL 配置主备模式,基于一台服务器的数据复制,故得名单机热备,主-备 Active-Standby主-备方式,即指的是一台服务器处于某种业务的激活状态 ...