c++的类和java的类机制着实不大一样,不仅仅是语法,还包括一些特殊的东西,如c++用友元函数来破坏类的封装性,使得外界(友元函数体)可以访问类的私有属性,而java呢,java则可以通过反射机制类在类的外部访问类的私有属性,从而破坏类的封装性,而不仅这点,java中没有什么运算符重载,而c++中提供了运算符重载技术使得我们自定义的类型(类)也可以想基本数据类型一样进行的运算符(+,-,*,/,%,…)运算。

c++友元函数

 类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。

友元函数例子

<span style="color:#000000"><code class="language-c++"><span style="color:#009900">#include <iostream></span><span style="color:#000088">using</span> <span style="color:#000088">namespace</span> <span style="color:#4f4f4f">std</span>;<span style="color:#000088">class</span> Obj{
<span style="color:#000088">public</span>:Obj(<span style="color:#000088">int</span> a,<span style="color:#000088">char</span> b){<span style="color:#000088">this</span>->a = a;<span style="color:#000088">this</span>->b = b;}<span style="color:#880000">// 友元函数,通过friend关键字声明</span><span style="color:#000088">friend</span> <span style="color:#000088">void</span> print(Obj obj);
<span style="color:#000088">private</span>:<span style="color:#000088">int</span> a;<span style="color:#000088">char</span> b;
};<span style="color:#000088">void</span> print(Obj obj){<span style="color:#4f4f4f">cout</span> << <span style="color:#009900">"a = "</span> << obj.a << <span style="color:#009900">"  c="</span> << obj.b<<endl;
}<span style="color:#000088">int</span> main(){Obj obj(<span style="color:#006666">10</span>,<span style="color:#009900">'h'</span>);<span style="color:#880000">// 类外部直接通过类名访问类属性,报错 error:'int obj::a' is private</span><span style="color:#880000">// cout << "a = " << obj.a << "  c=" << obj.b<<endl;</span><span style="color:#880000">// 类外部通过友元函数访问类私有成员</span>print(obj);
}
</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

上面的例子也可以这样写:

<span style="color:#000000"><code class="language-c++"><span style="color:#009900">#include <iostream></span><span style="color:#000088">using</span> <span style="color:#000088">namespace</span> <span style="color:#4f4f4f">std</span>;<span style="color:#000088">class</span> Obj{
<span style="color:#000088">public</span>:Obj(<span style="color:#000088">int</span> a,<span style="color:#000088">char</span> b){<span style="color:#000088">this</span>->a = a;<span style="color:#000088">this</span>->b = b;}<span style="color:#880000">// 友元函数,通过friend关键字声明</span><span style="color:#000088">friend</span> <span style="color:#000088">void</span> print(Obj obj){<span style="color:#4f4f4f">cout</span> << <span style="color:#009900">"a = "</span> << obj.a << <span style="color:#009900">"  c="</span> << obj.b<<endl;}
<span style="color:#000088">private</span>:<span style="color:#000088">int</span> a;<span style="color:#000088">char</span> b;
};<span style="color:#000088">int</span> main(){Obj obj(<span style="color:#006666">10</span>,<span style="color:#009900">'h'</span>);<span style="color:#880000">// 类外部直接通过类名访问类属性,报错 error:'int obj::a' is private</span><span style="color:#880000">// cout << "a = " << obj.a << "  c=" << obj.b<<endl;</span><span style="color:#880000">// 类外部通过友元函数访问类私有成员</span>print(obj);
}
</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

即友元函数体也放在类里面,这里调用友元函数方式不变

这说明了友元函数虽然定义在类内部,但那只是表示这个函数是这个类的友元,这个函数还是一个全局函数,而不是类的成员函数。

c++友元类

 c++友元类和友元函数一样都是类的友元,定义形式也是通过friend关键字,如:

<span style="color:#000000"><code class="language-c++"><span style="color:#009900">#include <iostream></span><span style="color:#000088">using</span> <span style="color:#000088">namespace</span> <span style="color:#4f4f4f">std</span>;<span style="color:#000088">class</span> A{
<span style="color:#000088">public</span>:A(<span style="color:#000088">int</span> a,<span style="color:#000088">int</span> b){<span style="color:#000088">this</span>->a = a;<span style="color:#000088">this</span>->b = b;}<span style="color:#880000">// 友元类,通过friend关键字声明</span><span style="color:#000088">friend</span> <span style="color:#000088">class</span> B;
<span style="color:#000088">private</span>:<span style="color:#000088">int</span> a;<span style="color:#000088">int</span> b;
};<span style="color:#000088">class</span> B{
<span style="color:#000088">public</span>:<span style="color:#000088">void</span> printA(A obj){<span style="color:#4f4f4f">cout</span> << <span style="color:#009900">"a = "</span> << obj.a << <span style="color:#009900">"  b = "</span> << obj.b <<endl;}
};<span style="color:#000088">int</span> main(){A obj(<span style="color:#006666">10</span>,<span style="color:#006666">20</span>);<span style="color:#880000">// 类外部通过友元访问类私有属性</span>B b;b.printA(obj);<span style="color:#880000">// 类外部直接通过类名访问类属性,报错 error:'int obj::a' is private</span><span style="color:#880000">// cout << "a = " << obj.a << "  b=" << obj.b<<endl;</span>
}</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

友元类和友元函数声明语句放在类中的那个位置都无所谓,也可以放在private修饰的域下面。

c++运算符重载

 C++提供运算符重载机制让我们重载 C++ 内置的运算符。这样,我们就可以使用自定义类型的运算符。重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。

如:

<span style="color:#000000"><code class="language-c++"><span style="color:#009900">#include <iostream></span><span style="color:#000088">using</span> <span style="color:#000088">namespace</span> <span style="color:#4f4f4f">std</span>;<span style="color:#000088">class</span> Complex{
<span style="color:#000088">public</span>:<span style="color:#000088">int</span> real;<span style="color:#000088">int</span> virt;Complex(<span style="color:#000088">int</span> real,<span style="color:#000088">int</span> virt){<span style="color:#000088">this</span>->real = real;<span style="color:#000088">this</span>->virt = virt;}Complex <span style="color:#000088">operator</span>+(Complex <span style="color:#000088">const</span> &c){<span style="color:#000088">return</span> Complex(<span style="color:#000088">this</span>->real+c.real,<span style="color:#000088">this</span>->virt+c.virt);}<span style="color:#880000">// 前置++</span>Complex& <span style="color:#000088">operator</span>++(){<span style="color:#000088">this</span>->real++;<span style="color:#000088">this</span>->virt++;<span style="color:#000088">return</span> *<span style="color:#000088">this</span>;}<span style="color:#880000">// 后置++,用参数占位符区别于前置++</span>Complex& <span style="color:#000088">operator</span>++(<span style="color:#000088">int</span>){Complex tmp(<span style="color:#000088">this</span>->real,<span style="color:#000088">this</span>->virt);<span style="color:#000088">this</span>->real++;<span style="color:#000088">this</span>->virt++;<span style="color:#000088">return</span> tmp;}<span style="color:#880000">// << >>运算符必须用友元函数才能重载</span><span style="color:#000088">friend</span> ostream& <span style="color:#000088">operator</span><<(ostream &out,Complex <span style="color:#000088">const</span> &c){out << c.real << <span style="color:#009900">" + "</span> << c.virt << <span style="color:#009900">"j"</span> <<endl;<span style="color:#000088">return</span> out;}
};<span style="color:#000088">int</span> main(){Complex c1(<span style="color:#006666">1</span>,<span style="color:#006666">2</span>),c2(<span style="color:#006666">3</span>,<span style="color:#006666">5</span>);Complex c3 = c1 + c2;<span style="color:#4f4f4f">cout</span> << <span style="color:#009900">"c3:"</span> << c3 <<endl;<span style="color:#4f4f4f">cout</span> << <span style="color:#009900">"c1:"</span> << c1 <<endl;++c1;<span style="color:#4f4f4f">cout</span> << <span style="color:#009900">"++c1:"</span> << c1 <<endl;<span style="color:#4f4f4f">cout</span> << <span style="color:#009900">"c2:"</span> << c2 <<endl;Complex c4 = c2++;<span style="color:#4f4f4f">cout</span> << <span style="color:#009900">"c2++:"</span> << c2 <<endl;<span style="color:#4f4f4f">cout</span> << <span style="color:#009900">"c4:"</span> << c4 <<endl;}</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62

结果:

可以看到我们的自定义类型-复数类型通过运算符重载机制实现了基本的运算符运算,使得我们自定义类型可以按照我们自己规定的运算规则进行运算。

这里总结了对自定义类型进行运算符重载的思路:

  1. 首先我们要知道我们要让我们自定义类型进行什么运算符运算,如要实现+法运算;
  2. 直接写出要运算的表达式,如c3 = c1 + c2
  3. 分析这是一个二目运算符,所以方法中需要两个参数,但是由于在类中有this指针,所以我们就省去了一个参数,这里就只需要例外一个参数了,所以写出方法头为Complex operator+(Complex const &c),这里为什么确定返回值为一个Complex也是根据我们的需要而定的(因为我们需要支持连加,但加得到的结果是一个新的Complex,所以不需要再返回值上加引用&)
  4. 确定好函数头就写函数体了,函数体就是要按照我们定义的规则进行代码实现即可。

说明:

  1. 实现运算符重载的函数也可以像其他函数一样函数体和函数声明分离,即函数体写在类外部或者一个cpp文件里面。
  2. 对于<<和>>运算符,要实现重载,只能通过友元函数实现,同时,这也是友元函数的真正的运用场景。对于每必要使用友元函数的地方就不要使用友元函数,这样可以提高程序的效率,也能避免一些意想不到的错误(滥用友元函数)。
  3. 对于前置++和后置++运算符,后置++的参数要使用参数占位符来和前置++相区别。
  4. 大部分的运算符都支持运算符重载,也有一些运算符不可以重载(::,?:,.*)。

版权声明:本文为博主原创文章,欢迎大家转载,转载请标明本文出自:<a href='http://blog.csdn.net/ydxlt' /> https://blog.csdn.net/ydxlt/article/details/50987448

c++友元函数及运算符重载相关推荐

  1. 第九天2017/04/18(1、友元函数、运算符重载)

    1.成员函数和全局函数(友元函数)转换的技巧 从类的成员函数转换为全局函数,只需要加一个this指针: 从全局函数转换为类的成员函数,需要减去一个左操作数参数.[友元函数.成员函数]唯一的区别:友元函 ...

  2. 关于友元函数,运算符重载和类的类型转换

    一 关于运算符的重载: 运算符中有10种是不可重载的: sizeof static_cast<type> . dynamic_cast<type> .* const_cast& ...

  3. 【黑马程序员 C++教程从0到1入门编程】【笔记4】C++核心编程(类和对象——封装、权限、对象的初始化和清理、构造函数、析构函数、深拷贝、浅拷贝、初始化列表、友元friend、运算符重载)

    黑马程序员C++教程 文章目录 4 类和对象(类属性[成员属性],类函数[成员函数]) 4.1 封装 4.1.1 封装的意义(三种权限:public公共.protected保护.private私有)( ...

  4. 成员函数和友元函数实现一元运算符重载

    使用友元函数实现一元运算符的重载 实现一元运算符的前置重载 即前置++a; #include <iostream> using namespace std;class Complex { ...

  5. [C++]分数类的定义(成员函数、运算符重载)

    [C++]分数类的定义(成员函数.运算符重载) 1 分数类成员和成员函数 1.1 分数类成员 1.2 分数类的成员函数 1.3 分数类的io操作 1.4 分数类的预定义 2 成员函数定义 2.1 化简 ...

  6. C++友元与输出运算符重载

    #pragma once #include <ostream> #include <iostream> using namespace std;class MyComplex ...

  7. 3-5:类与对象中篇——默认成员函数之运算符重载

    文章目录 一:运算符重载 (1)运算符重载 A:为什么要有运算符重载? B:如何进行运算符重载 C:注意 (2)赋值运算符重载 二:const修饰类的成员函数 一:运算符重载 C++ 允许在同一作用域 ...

  8. C++运算符重载(友元函数方式)

    我们知道,C++中的运算符重载有两种形式:①重载为类的成员函数(见C++运算符重载(成员函数方式)),②重载为类的友元函数. 当重载友元函数时,将没有隐含的参数this指针.这样,对双目运算符,友元函 ...

  9. C++:运算符重载函数之成员运算符重载函数

    5.2.3 成员运算符重载函数 在C++中可以把运算符重载函数定义为某个类的成员函数,称之为成员运算符重载函数. 1. 定义成员运算符重载函数的语法形式 (1)在类的内部,定义成员运算符重载函数的格式 ...

最新文章

  1. 输入法大战,你用哪家输入法? | 每日趣闻
  2. 大话数据结构——查找
  3. 树莓派摄像头基础配置及测试
  4. 使用PostgREST构建PostgreSQL数据库的REST风格API
  5. moco常用配置参数及实战
  6. zabbix安装以及监控(一)
  7. こだわり者いろはちゃん / Iroha's Obsession (暴力枚举)
  8. 378.有序矩阵中第K小的元素
  9. 关于Boost的Asio的信号灯超时时间已到错误
  10. java 一年 周数_java获取一年共有多少周
  11. 00002__Proxyee-down__百度网盘下载加速软件
  12. Completed 403 FORBIDDEN 后端解决跨域问题
  13. mysql的填充因子_数据库SQL Server – 索引 – 填充因子
  14. 京东运营 不错的帖子
  15. 【Maxent物种分布模型】气候变化对响尾蛇地理分布的影响
  16. 什么是根域名服务器?
  17. oracle将其他字段类型改为clob类型方法
  18. Internet 上可用的“简单网络时间协议”时间服务器列表
  19. 微型计算机的显卡,来看一款冷酷的游戏显卡,XFX讯景Radeon RX 6700XT海外版OC评测解析...
  20. 爆款营销打破空间局限,新商云提高门店坪效

热门文章

  1. 4.3 SE38数据输出
  2. SAP MM模块-实施顾问岗位-面试手册-面试总结
  3. STL之Vector(Linux内核)完整实现
  4. 升级 项目跑不起来_不做“睡城”!嘉定新城“十四五”加速度,产城融合跑起来,远香湖,看好你...
  5. python实现根据文件名找出(拷贝/剪切)同名文件的不同类型文件
  6. Dataloader与Dataset
  7. jQuery UI基础 学习笔记
  8. layui弹出层:皮肤扩展(文档解读)
  9. 彩虹云任务极致精简版--PHPcron程序
  10. python动态执行语句_Python Language