第九天2017/04/18(1、友元函数、运算符重载)
来源:互联网 发布:sam软件csp 编辑:程序博客网 时间:2024/05/17 15:06
1、成员函数和全局函数(友元函数)转换的技巧
从类的成员函数转换为全局函数,只需要加一个this指针;从全局函数转换为类的成员函数,需要减去一个左操作数参数。【友元函数、成员函数】唯一的区别: 友元函数中没有this指针,而成员函数中有this————>因此友元函数的参数要比成员函数的参数多一个。【技巧】 友元函数的多出来的参数相当于成员函数中隐藏的this指针指向的对象*this,例如: friend String operator+(const String& s1,const String& s2); //s1的作用 String operator+(const String& s); //相当于成员函数中的*this friend String operator+(const String& s,const char* str);//s的作用 String operator+(const char* str); //相当于成员函数中的*this friend String operator+=(String& s1, const String& s2); //s1的作用 String operator+=(const String& s);//相当于成员函数中的*this friend 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);
1 0
- 第九天2017/04/18(1、友元函数、运算符重载)
- 第8周项目1-实现复数类中的运算符重载(友元函数)
- 8-1-2 运算符重载(友元函数)
- 第12周项目1 使用友元函数进行运算符重载
- 第12周项目-复数类中的运算符重载(2)(友元函数)
- 第8周项目1(2)实现复数类中的运算符重载(友元函数)
- 第8周任务1-2(使用类的友元函数完成运算符的重载)
- 运算符重载与友元函数
- c++ 运算符重载 友元函数
- 利用友元函数,重载运算符
- 友元函数重载运算符
- 运算符重载为友元函数
- 重载运算符以及友元函数
- 7.10友元函数重载运算符
- 运算符重载和友元函数
- 友元函数编写运算符重载
- 友元函数编写运算符重载
- C++ 重载运算符 友元函数
- Beautiful People ZOJ
- 指针数组和数组指针的区别
- POJ 2828 Buy Tickets(线段树)
- Android自动化测试框架Espresso(一)——简介
- spring事务回滚
- 第九天2017/04/18(1、友元函数、运算符重载)
- spring建立websocket例子
- UICenterOnChild
- bzoj 3282 LCT
- 【qscoj】哗啦啦村的奇迹果实(一)
- 杂记
- bzoj4810 [Ynoi2017]由乃的玉米田 莫队+bitset
- Java进阶(五十七)-基于感知哈希算法的pHash图像配准算法
- 仿QQ聊天界面侧滑