C++重载(主要介绍使用友元函数重载)
重载限制
多数C++运算符都可以用下面的方式重载。重载的运算符不必是成员函数,但必须至少有一个操作数是用户自定义的类型。下面详细介绍C++对用户定义的运算符重载的限制。
1 重载后的运算符必须至少有一个操作数是用户自定义的类型,这将防止用户为标准类型重载运算符。因此,不能将减法运算符(-)重载为double值的和,而不是它们的差。虽然这种限制将对创造性有所影响,但可以确保程序正常运行。
2 使用运算符时不能违反运算符原来的句法规则。例如,不能将求模运算符(%)重载成使用一个操作数。
同样,不能修改运算符的优先级。因此,如果将加号运算符重载成将两个类相加,则新的运算符与原来的加号具有相同的优先级。
3 不能创建新的运算符。例如,不能定义operator**()函数来表示求幂。
4 不能重载下面的运算符
- sizeof:sizeof运算符
- .:成员运算符
- .*:成员指针运算符
- :: :作用域解析运算符
- ?::条件运算符
- typeid:一个RTTI运算符
- const_cast:强制类型转换运算符
- dynamic_cast:强制类型转换运算符
- reinterpret_cast:强制类型转换运算符
- static_cast:强制类型转换运算符
然而,下表中的所有运算符都可以被重载
5 下表中的大多数运算符都可以通过成员或非成员函数进行重载,但下面的运算符值能通过成员函数进行重载
- =:赋值运算符
- ():函数调用运算符
- []:下标运算符
- ->:通过指针访问类成员的运算符
可重载的运算符


除了这些正式限制之外,还应在重载运算符时遵循一些限制。例如,不要将*运算符重载成交换两个对象的数据成员。
友元
C++控制对类对象私有部分的访问。通常,公有类方法提供唯一的访问途径,这种限制太严格,以至于不适合特定的编程问题。在这种情况下,C++提供了另外一种形式的访问权限:友元。
友元有3种:
- 友元函数
- 友元类
- 友元成员函数
通过让函数成为类的友元,可以赋予该函数与类的成员函数相同的访问权限。
对于一个二元运算符,如果使用一个类对象和一个double类型进行操作
例如:
A=B*2.75
将被转换为下面的成员函数调用:
A=B.operator*(2.75);
但下面的语句又如何呢?
A=2.75*B;
从概念上讲,这两个表达式应该相同,但是第二个表达式不对应于成员函数,因为2.75不是类对象。记住,左侧的操作数应是调用对象,但2.75不是对象。因此,编译器不能使用成员函数调用替换该表达式。
解决这个难题的一种方式是——费成员函数(记住,大多数运算符都可以通过成员或非成员函数来重载)。非成员函数不是由对象调用的,它使用的所有值(包括对象)都是显示参数。这样,编译器能够将下面的表达式:
A=2.75*B;
与下面的非成员函数调用匹配:
A=operator*(2.75,B);
该函数的原型如下:
class1 operator*(double m,const class1 &t);
对于非成员重载运算符函数来来说,运算符表达式左边的操作数对应于运算符函数的第一个参数,运算符表达式右边的操作数对应于运算符函数的第二个参数。而原来的成员函数则按相反的顺序处理操作数,也就是说,double值乘以class1值。
使用非成员函数可以按所需的顺序获得操作数(先double,然后是class1),但引发了一个新问题:非成员函数不能直接访问类的私有数据,至少常规非成员函数不能访问。然而,有一类特殊的非成员函数可以访问类的私有成员,它们被称为友元函数。
创建友元
创建友元的第一步是将其原型放在类声明中,并在原型声明前加上关键字friend:
friend class1 operator*(double m,const class1 & t);
该原型意味着下面两点:
- 虽然operator*()函数是在类声明中声明的,但他不是成员函数,因此不能使用成员运算符来调用;
- 虽然operator*()函数不是成员函数,但它与成员函数的访问权限相同。
第二步的编写函数定义。因为它不是成员函数,所以不要使用成员限定符::。另外,不要再定义中使用关键字friend。定义应该如下:
class1 operator*(double m,const class1 &t)
{}
有了上述声明和定义后,下面的语句:
A=2.75*B;
将转换为如下语句,从而调用刚才定义的非成员友元函数:
A=operator*(2.75,B);
总之,类的友元函数是非成员函数,其访问权限与成员函数相同。
实际上,按下面的方式对定义进行修改(交换乘法操作数的顺序),可以将这个友元函数编写为非友元函数:
class1 operator*(double m,const class1 &t)
{
return t*m;//use t.operator*(m)
}
这个版本将class1对象t作为一个整体使用,让成员函数类处理私有值,因此不必是友元。然而,将该版本作为友元也是一个好主意。最重要的是,它将作为正式类接口的组成部分。其次,如果以后发现需要函数直接访问私有数据,则只要修改函数定义即可,而不必修改类原型。
提示:如果要为类重载运算符,并将非类的项作为其第一个操作数,则可以使用友元函数来反转操作数的顺序。。
C++重载(主要介绍使用友元函数重载)的更多相关文章
- C++友元函数重载"++"和"--"运算符
代码: #include <iostream> #include <cstring> using namespace std; class one{ public: one(i ...
- C++走向远洋——49(项目一2、复数类中的运算符重载、类的友元函数)
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.cpp * 作者:常轩 * 微信公众号:Worldhe ...
- C++运算符重载三种形式(成员函数,友元函数,普通函数)详解
首先,介绍三种重载方式: //作为成员函数重载(常见) class Person{ Private: string name; int age; public: Person(const char* ...
- C++:运算符重载函数之友元运算符重载
5.2.2 友元运算符重载函数 运算符重载函数一般采用两种形式定义: 一是定义为它将要操作的类的成员函数(简称运算符重载函数): 二是定义为类的友元函数(简称为友元运算符重载函数). 1.定义友元运算 ...
- C++基础——运算符重载友元函数示例
一.前言 其实本人学习C++的目的,只是为了体会OOP设计思想,并为利用System Verilog验证复杂设计做准备.如果想要真正做点软件方面项目级的东西,还需要掌握其他高级语言和库.框架等知识.因 ...
- C++运算符重载(友元函数方式)
我们知道,C++中的运算符重载有两种形式:①重载为类的成员函数(见C++运算符重载(成员函数方式)),②重载为类的友元函数. 当重载友元函数时,将没有隐含的参数this指针.这样,对双目运算符,友元函 ...
- 初探C++运算符重载学习笔记<2> 重载为友元函数
初探C++运算符重载学习笔记 在上面那篇博客中,写了将运算符重载为普通函数或类的成员函数这两种情况. 以下的两种情况发生.则我们须要将运算符重载为类的友元函数 <1>成员函数不能满足要求 ...
- c++函数重载---2
原创博客:转载请标明出处:http://www.cnblogs.com/zxouxuewei/ 写在前面: 函数重载的重要性不言而明,但是你知道C++中函数重载是如何实现的呢(虽然本文谈的是C++中函 ...
- C++的函数重载 转
——每个现象后面都隐藏一个本质,关键在于我们是否去挖掘 写在前面: 函数重载的重要性不言而明,但是你知道C++中函数重载是如何实现的呢(虽然本文谈的是C++中函数重载的实现,但我想其它语言也是类似的) ...
随机推荐
- lightoj 1022
直接算即可,特别要注意精度 #include<cstdio> #include<cmath> int main(){ int t, CASE(0); double r; sca ...
- UIButton 设置为圆形,并且使用图片(UIImage)当做背景
-(UIButton *)shareButtonWithIcon:(NSString *)iconName { UIButton *button = [UIButtonbuttonWithType:U ...
- <转>如何测试一个杯子
在软件测试的面试中, 经常会碰到类似的问题. 比如:如何测试一个杯子, 或者如何测试一只笔. 要求你设计20个以上的test case. 这类的面试题目,是考察面试者是否熟悉各种软件测试方法, 设计t ...
- 使用七牛云存储----大家自己的图床[python]
##写博客什么的总得贴图吧,图床选来选去还是七牛吧.嗯,就是你了 [OSchaina 源码] 结合FastStone Capture 简直爽歪歪. FastStone Capture 自动保存图片到文 ...
- MFC最大化显示任务栏
今天2016-07-23 13:26:24又来处理最大化时,窗口任务栏隐藏的bug. 前面已经用了 MINMAXINFO的结构体: typedef struct { POINT ptReserve ...
- Linux重复执行上条命令
Linux系统下Shell重复执行上条命令的 4 种方法: 1.使用上方向键,并回车执行.2.按 !! 并回车执行.3.输入 !-1 并回车执行.4.按 Ctrl+P 并回车执行.
- 恒天云技术分享系列5 – 虚拟化平台性能对比(KVM & VMware)
恒天云技术分享系列:http://www.hengtianyun.com/download-show-id-14.html 概述 本性能测试报告将详细陈述各虚拟化平台基准性能测试的主要结论和详细结果. ...
- 软件工程 --- Pair Project: Elevator Scheduler [电梯调度算法的实现和测试] [附加题]
软件工程 --- Pair Project: Elevator Scheduler [电梯调度算法的实现和测试] [附加题] 首先,在分组之前,我和室友薛亚杰已经详细阅读了往届学长的博客,认为电梯调度 ...
- Red5点播和直播的实现
(一) Red5流媒体服务器介绍Red5是一个采用Java开发开源的Flash流媒体服务器.它支持:把音频(MP3)和视频(FLV)转换成播放流: 录制客户端播放流(只支持FLV):共享 ...
- Git使用过程中出现项目文件无法签入Source Control的情况
在VS中使用Git进行项目source control的过程中,有些文件不在source control之下,右键点击时,也找不到Undo, Commit命令 无法把他们签入进Source Contr ...