第九天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);   //相当于成员函数中的*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);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值