第九天2017/04/18(1、友元函数、运算符重载)
1、成员函数和全局函数(友元函数)转换的技巧
从类的成员函数转换为全局函数,只需要加一个this指针;
从全局函数转换为类的成员函数,需要减去一个左操作数参数。【友元函数、成员函数】唯一的区别:友元函数中没有this指针,而成员函数中有this————>因此友元函数的参数要比成员函数的参数多一个。
【技巧】友元函数的多出来的参数相当于成员函数中隐藏的this指针指向的对象*this,例如:friend String operator+(const String& s1,const String& s2); //s1的作用String operator+(const String& s); //相当于成员函数中的*thisfriend String operator+(const String& s,const char* str);//s的作用String operator+(const char* str); //相当于成员函数中的*thisfriend String operator+=(String& s1, const String& s2); //s1的作用 String operator+=(const String& s);//相当于成员函数中的*thisfriend String operator+=(String& s,const char* str);//s的作用String operator+=(const char* str);//相当于成员函数中的*this
2、友元函数
//详细讲解:operator+函数的返回值是对象?还是对象的引用?以及各自对应的正确写法!
#include <iostream>
using namespace std;
class Complex
{public:Complex(double r=0,double i=0) {real=r;imag=i;}
//重载函数作为友元函数
//形式1:错误friend Complex& operator+(Complex &c1,Complex &c2) //【此处代码是错误的】返回的是引用Complex& {Complex tmp;tmp.real = c1.real+c2.real;tmp.real = c1.imag+c2.imag;return tmp;//返回一个临时对象的简写:return Complex(c1.real+c2.real, c1.imag+c2.imag);可以修改成:在被调函数中动态给对象分配空间,这样可以把结果甩出去// Complex *tmp = new Complex;// tmp->real = c1.real+c2.real;// tmp->real = c1.imag+c2.imag;// return *tmp;}//分析形式1为什么错误? 答:因为返回值为对象的引用时,返回的内容如果是临时对象,在函数//执行结束后,临时对象被析构,因此返回一个无效的值。
//形式2:正确friend Complex operator+(Complex &c1,Complex &c2) //【此处代码是正确的】返回的是对象Complex{Complex tmp;tmp.real = c1.real+c2.real;tmp.real = c1.imag+c2.imag;return tmp;//返回一个临时对象的简写:return Complex(c1.real+c2.real, c1.imag+c2.imag);}//分析形式2为什么正确? 答:因为返回值为对象时,“调用时operator+(c1,c2);返回的//内容也是临时对象”,但是返回时会调用拷贝构造函数另外创建一个对象来保存临时对象tmp的//值,因此尽管在函数执行结束后,临时对象被析构,但是拷贝构造出来的对象可以返回给主函//数,被主函数中的对象接受。void display(){cout<<"real="<<real<<","<<"imag="<<imag<<endl;}
private:double real;double imag;
};
int main( )
{Complex c1(3,4),c2(5,1),c3;c3=c1+c2;c1.display();c2.display();c3.display();
}
3、运算符重载
注:
不能重载的运算符有 . .* sizeof :: ?:
常用的重载运算符有 [] = ++ – == !=
C++中不能用友元函数重载的运算符有: = ( ) [ ] ->
#include <iostream>
using namespace std;
class Complex
{
public:
//构造函数:写成下面三个,看起来啰嗦,其实是为了防止调用时发生二义性Complex(){real=0; imag=0;} Complex(double r,double i) {real=r;imag=i;}Complex(double r){real=r;imag=0;} //转换构造函数/*-------------------------------------------------------------------*/
//重载 +
//case1:重载运算符函数为成员函数(左操作数由this指针传递,右操作数由参数传递)Complex operator-(Complex & obj) //返回类型Complex {Complex tmp;tmp.real = real+obj.real;tmp.imag = imag+obj.imag;return tmp;}
//case2:重载运算符函数为友元函数(左、右操作数由参数传递)friend Complex operator+(const Complex& c1,const Complex& c2) //返回类型Complex{return Complex(c1.real+c2.real, c1.imag+c2.imag); }
/*-------------------------------------------------------------------*/
//重载前置++、--Complex& operator--() //成员函数{return Complex(--real,--imag); // 返回类型都是引用Complex&}friend Complex& operator++(Complex& obj) //友元函数{return Complex(++obj.real,++obj.imag); //形参和返回类型都是引用Complex&}
//重载后置++、--Complex operator++(int) //成员函数{Complex tmp = *this;this->real++;this->imag++;return tmp;}friend Complex operator--(Complex& obj,int) //友元函数{Complex tmp = obj;obj.real--;obj.imag--;return tmp;}
/*-------------------------------------------------------------------*/
//重载 <<friend ostream& operator<<(ostream& out,Complex& obj) {out<<"real="<<obj.real<<","<<"imag="<<obj.imag;return out;}//friend void operator<<(ostream& out,Complex& obj) //这样不能连续输出//{// out<<"real="<<obj.real<<","<<"imag="<<obj.imag;//}
//【疑问】为什么返回值是ostream& ,而不是void?//【答】为了能够连续的输出; || 注:函数返回值当作左值,则必须返回一个引用!
/*-------------------------------------------------------------------*/
private:double real;double imag;
};int main()
{Complex c1(3,4),c2(5),c3;c3 = c1 + c2;//cout<<c1;//等价于operator<<(cout,c1);,调用完成后,返回值为cout,可以作为左值继续输出!cout<<c1<<endl; //等价于operator<<(operator<<(cout,c1),c1);cout<<c2<<endl;cout<<c3<<endl;c3 = 20 + c3; //这种情况必须用友元函数cout<<c3<<endl;c3--;cout<<c3<<endl;
}
【总结规律】//【返回类型:对象Complex、String】
① + - * / % += -= *= /= %= 基本的四则运算friend String operator+(const String& s1,const String& s2);String operator+(const String& s); friend String operator+(const String& s,const char* str);String operator+(const char* s); friend String operator+=(String& s1, const String& s2); String operator+=(const String& s);friend String operator+=(String& s,const char* str);String operator+=(const char* str);
②单目运算符:后置++、后置--Complex operator++(int); friend Complex operator--(Complex& obj,int);
------------------------------------------------------------------------
//【返回类型:对象的引用Complex&、String&】
Complex& operator--();//前置++、前置--
①连续操作:>> 、 << 、 赋值=friend ostream& operator<<(ostream& out,Complex& obj);Complex& operator=(const Complex& obj);
②返回值作为“左值”char& operator[](int i); // []操作符========================================================================================
【综合示例】
//String类
//-------------------------------------------------------------------
//重载 = :返回的是String&,“连等a=b=c”String& operator=(char *s);String& operator=(const String& s);
//-------------------------------------------------------------------
//重载 + :返回的是String (s=s1+s2;因为如果用String&,会使在执行完+后,s1的值也发生变化)//friend String operator+(const String& s1,const String& s2);String operator+(const String& s); //friend String operator+(const String& s,const char* str);String operator+(const char* s);
//重载 += :返回的是String//friend String operator+=(String& s1, const String& s2); String operator+=(const String& s);//friend String operator+=(String& s,const char* str);String operator+=(const char* str);
//-------------------------------------------------------------------
//重载 [] :返回的是char&char& operator[](int i);const char& operator[](int i) const;
//重载 << >> :返回的是ostream&friend ostream& operator<<(ostream &out,String &s);friend istream& operator>>(istream &in ,String &s);
//-------------------------------------------------------------------
//friend函数:重载> < == != friend bool operator<(const String& s1,const String& s2);friend bool operator>(const String& s1,const String& s2);friend bool operator==(const String& s1,const String& s2);friend bool operator!=(const String& s1,const String& s2);
第九天2017/04/18(1、友元函数、运算符重载)相关推荐
- 第九天2017/04/18(2、类的继承、面试题:继承访问修饰符、组合、static、构造、多态)
继承:可以使用原来的代码,代码复用 多态:代码复用.接口复用,用基类的指针"根据对象"调用"指定对象的函数". 1.继承.访问修饰符//C++类成员的3种访问级 ...
- 第九天2017/04/18(4、非虚继承、虚继承的本质 / sizeof)
case1:非虚继承 上面是代码的继承图 #include<iostream> using namespace std; //抽象基类:动物类 class CAnimal { public ...
- 第九天2017/04/18(3、重载/覆盖 PK 重写/重定义、父类子类混搭风、抽象类)
1.重载/覆盖 PK 重写/重定义 [预备知识] 函数重载必须在同一个类中发生子类无法重载父类的函数,父类同名的函数将会被名称覆盖重载是在编译期间根据参数类型和个数决定函数调用重载只放在同一个类之中, ...
- C++——运算符的重载---以成员函数方式重载---以友元函数方式重载
一.运算符的重载 1.运算符的重载 允许把标准运算符(如+ - * /等运算符)应用于自定义数据类型的对象,可以提高程序的可读性,运算符的重载本质上还是函数重载.运算符仅仅是语法上的方便,它是另一种函 ...
- 【C++ 七】类和对象:封装、继承、多态、友元、运算符重载
封装.继承.多态.对象的初始化和清理.C++对象模型和this指针.友元.运算符重载 文章目录 封装.继承.多态.对象的初始化和清理.C++对象模型和this指针.友元.运算符重载 前言 1 封装 1 ...
- 200912阶段一C++友元、运算符重载
目录 一.学习的知识点 回顾 友元 友元函数 友元类 运算符重载 二.上课没有听懂或者没有理解的地方 三.当天学习的收获 四.作业的思路.不会的地方 五.其他需要反馈的问题 六.心得体会 一.学习的知 ...
- 笔记②:牛客校招冲刺集训营---C++工程师(面向对象(友元、运算符重载、继承、多态) -- 内存管理 -- 名称空间、模板(类模板/函数模板) -- STL)
0618 C++工程师 第5章 高频考点与真题精讲 5.1 指针 & 5.2 函数 5.3 面向对象(和5.4.5.5共三次直播课) 5.3.1 - 5.3.11 5.3.12-14 友元 友 ...
- C++阶段03笔记02【类和对象(封装、对象的初始化和清理、对象模型和this指针、友元、运算符重载、继承、多态)】
C++| 匠心之作 从0到1入门学编程[视频+课件+笔记+源码] 目录 1.内存分区模型 2.引用 3.函数提高 4.类和对象 4.1.封装 4.1.1.封装的意义 --实例1:设计圆类 --实例2: ...
- C++ 笔记(30)— 友元函数与友元类
我们知道类的私有成员只能在类的成员函数内部访问,如果想在别处访问对象的私有成员,只能通过类提供的接口(成员函数)间接地进行.这固然能够带来数据隐藏的好处,利于将来程序的扩充,但也会增加程序书写的麻烦. ...
最新文章
- Codechef REBXOR[dp+字典树]
- android本地存储SharedPreferences
- CSS 魔法系列:纯 CSS 绘制基本图形(圆、椭圆等)
- python大小写转换if_python代码实例大小写转换,首字母大写,去除特殊字符
- 进阶篇-安卓系统:5.安卓手机位置传感器
- 【BZOJ-1502】月下柠檬树 计算几何 + 自适应Simpson积分
- 阿里舆情︱舆情热词分析架构简述(Demo学习)
- MySQL空间索引简单使用
- psd文件怎样导出html5,PSD格式的文件怎么转换成CAD格式?
- 浅析某城商行手机银行水平授权漏洞问题
- Mtk平台出现NE的分析简记
- 【面试题】京东大数据面试真题汇总,收藏必备
- R语言-出图时的中英文字体解决方案
- Context的翻译
- 计算机管理没有本地用户和组控制面板,win10管理没有本地用户和组怎么办_win10电脑管理没有本地用户和组解决方法...
- PRML 读书笔记 chapter1 Introduce
- qt 飞扬青云_Qt编写安防视频监控系统(界面很漂亮)
- FOTA升级apply_patch解析
- Python list 统计各个元素频次
- Android R.java类的手动生成