C++中的操作符重载

1.不能重载的: . :: .* ?: sizeof
2.操作符重载是通过函数实现的。

class Complex
{

publicint a,b;
public:
    Complex(int a=0,int b=0)
    {
        this->a =a;
        this->b =b;
    }

    void printCom()
    {
        std::cout<<this->a<<" + "<<this->b<<"i\n";
    }
};

Complex complexAdd(Complex &c1,Complex &c2)
{
    Complex tmp;
    tmp.a = c1.a + c2.a;
    tmp.b = c1.b + c2.b;
    return tmp;
}

Complex operator+(Complex &c1,Complex &c2)
{
    Complex tmp;
    tmp.a = c1.a + c2.a;
    tmp.b = c1.b + c2.b;
    return tmp;
}

void main()
{
    Complex c1(1,2),c2(3,4);
    //如果没有重载+操作符,c1+c2是会出错的。
    //int是基础数据类型,C++编译器已经为这些类型提供了+号操作
    //自定义数据类型需要自己重载运算符操作。

    //1.我们通过全局函数,实现两个复数的相加,但是还要写函数名,太麻烦了,不直观。
    //Complex c3 = complexAdd(c1,c2);

    //2.我们将全局函数名改为operator+
    //这样我们就可以像下面这样调用operator+函数,和普通的函数调用方法是一致的。
    //Complex c3 = operator+(c1,c2);
    //3.现在我们直接写c1+c2竟然没报错,也能运行,说明,操作符重载本质上就是函数调用。
    //c2 = c1 + c2;//重载 + 号运算符

    system("pause");
}

操作符重载的两种方法:
1.友元函数实现操作符重载
注意到没有,我们的Complex类中的a,b成员变量是public的,这样全局重载函数在外部才能访问类的公有成员,但是一般情况下,我们将类的成员变量设置为私有的。那么就不能再使用全局重载函数了,有两种解决方案,一种是友元函数实现,一种是成员函数实现 。我们先看友元函数实现,其实很简单。我们只要将前面的全局重载函数声明为Complex类的友元函数即可,这样友元函数在外部就可以访问类的私有成员变量。

class Complex
{
/*public*/
private:
    int a,b;
    //通过友元函数实现 + 号重载
    friend Complex operator+(Complex &c1,Complex &c2);

public:
    Complex(int a=0,int b=0)
    {
        this->a =a;
        this->b =b;
    }

    void printCom()
    {
        std::cout<<this->a<<" + "<<this->b<<"i\n";
    }
}
Complex operator+(Complex &c1,Complex &c2)
{
    Complex tmp;
    tmp.a = c1.a + c2.a;
    tmp.b = c1.b + c2.b;
    return tmp;
}

2.成员函数实现操作符重载
另一种实现访问私有变量的方法就是通过使用成员函数。
注意:左操作数被隐藏在this指针中。

class Complex
{

/*public*/
private:
    int a,b;

public:
    Complex(int a=0,int b=0)
    {
        this->a =a;
        this->b =b;
    }

    void printCom()
    {
        std::cout<<this->a<<" + "<<this->b<<"i\n";
    }

    //通过类的成员函数,实现 - 号重载。
    //注意:隐藏了this指针
    Complex operator-(Complex &c2)
    {
        Complex tmp;
        tmp.a = this->a - c2.a ;
        tmp.b = this->b - c2.b ;
        return tmp;
        //这里返回Complex&好不好???
        //不好。因为 tmp是临时对象,当函数指向完毕之后,会被析构,而返回的是一个匿名对象,该匿名对象是由拷贝构造函数创建的。
        //因为tmp 被析构会清空其内存,如果其中有指针成员的话,指针指向的内存也会被释放,如果匿名对象是由浅拷贝创建的话,则匿名对象中的指针是野指针。

        //如果返回c2对象的话,则可以返回引用。为啥?
        //因为c2已经存在,作为形参,只是一个引用,它的生命周期与当前函数无关,返回引用也是没有问题的。
    }
}

void main()
{
    Complex c1(1,2),c2(3,4);
    //通过成员函数 实现  重载 - 号 操作符
    //Complex c4 = c1.operator-(c2);
    //上面的调用方法和下面是等价的。因为是成员函数,所以可以使用类的对象点出方法来。
    Complex c4 = c1 - c2;

}

接下来,看看单操作数的操作符重载。

1.前置++(–)重载

class Complex
{
/*public*/
private:
    int a,b;

    //前置 ++
    friend Complex& operator++(Complex &c2);

public:
    Complex(int a=0,int b=0)
    {
        this->a =a;
        this->b =b;
    }

    void printCom()
    {
        std::cout<<this->a<<" + "<<this->b<<"i\n";
    }

    //使用成员函数实现  前置 --
    Complex& operator--()
    {
        this->a --;
        this->b--;

        return *this;
    }
};

//全局函数实现前置++,在类中声明为类的友元函数
//这里一般返回值为类的引用而不是一个匿名对象
Complex& operator++(Complex &c2)
{
    c2.a ++;
    c2.b ++;

    return c2;
}

void main()
{
    Complex c1(1,2),c2(3,4);

    //全局函数实现
    ++c1;
    c1.printCom();

    //类成员函数实现
    --c2;
    c2.printCom();

    system("pause");
}

2.后置++(–)重载
因为后置++的重载函数和前置++的重载函数参数和名称都一样,C++为了以示区别,在后置++的重载函数的参数中多加了一个int参数,just为了区别前置++,没有任何意义。

class Complex
{

/*public*/
private:
    int a,b;

    //全局函数实现后置 ++
    //后置++ ,先使用c2的属性,再让c2 的属性++
    friend Complex operator++(Complex &c2,int);//int只是一个占位参数,为了和前置++区分

public:
    Complex(int a=0,int b=0)
    {
        this->a =a;
        this->b =b;
    }

    void printCom()
    {
        std::cout<<this->a<<" + "<<this->b<<"i\n";
    }

    //成员函数实现后置 --
     Complex operator--(int)
     {
         Complex tmp = *this;

         this->a --;
         this->b --;

         return tmp;
     }
};

//全局函数实现后置++
// 为啥返回返回一个对象,而不是一个引用?
// 因为,Complex tmp是一个局部对象,该函数调用结束之后tmp对象会被回收,C++通过在内存中创建一个匿名对象,将tmp的内存拷贝给匿名对象返回,所以,这里返回一个匿名对象比较合适。
 Complex operator++(Complex &c2,int)
 {
    //先使用c2的属性,再让c2 的属性++
     Complex tmp ;
     tmp = c2;

     c2.a ++;
     c2.b ++;

     return tmp;
 }
void main()
{

    Complex c1(1,2),c2(3,4);

    //全局函数实现后置++
    c1++;
    c1.printCom();
    //类成员函数实现后置--
    c2--;
    c2.printCom();

    system("pause");

}

友元函数重载和成员函数重载的区别?
什么时候该用友元函数重载,什么时候该用成员函数重载呢?我们先看下面的例子。

#include <iostream>

class Complex
{
private:
    int a,b;

    //重载 << 运算符
    friend void operator<< (std::ostream &out , Complex &c2);

public:
    Complex(int a=0,int b=0)
    {
        this->a =a;
        this->b =b;
    }

    void printCom()
    {
        std::cout<<this->a<<" + "<<this->b<<"i\n";
    }
};

//使用全局函数实现<<重载
//可以使用类成员函数实现<<重载吗?
//不能,因为ostream类的源代码我们不能修改,所以只能使用全局函数结合友元函数实现<<重载
//这是友元函数存在的最大的意义,一般情况下友元函数都用在于此,其他情况都不建议使用友元函数。
void operator<<(std::ostream &out , Complex &c2)
{
    std::cout<<c2.a<<" + "<<c2.b<<"i\n";
}


void main()
{
    Complex c1(1,2),c2(3,4);

    //如果我们希望使用cout<<c1输出c1则需要重载<<操作符。
    //重载 << 运算符

    //1.使用友元函数
    //std::cout<<c1;

    //2.能不能使用成员函数
    // cout.operator<<(std::ostream &out , Complex &c2)
    // cout.operator<<(Complex &c2)
    // 这样就需要在cout类的成员函数中加一个上述的函数,这是不可能的。
    // 所以向这种操作符重载只能使用友元函数重载。

    system("pause");
}

如何实现链式编程

#include <iostream>

class Complex
{
private:
    int a,b;

    //重载 << 运算符
    //如何实现 << 链式编程 --> 返回对象的引用
    friend std::ostream& operator<<(std::ostream &out , Complex &c2);

public:
    Complex(int a=0,int b=0)
    {
        this->a =a;
        this->b =b;
    }

    void printCom()
    {
        std::cout<<this->a<<" + "<<this->b<<"i\n";
    }
};

std::ostream& operator<<(std::ostream &out , Complex &c2)
{
    std::cout<<c2.a<<" + "<<c2.b<<"i\n";
    return out;
}

void main()
{
    Complex c1(1,2),c2(3,4);

    //重载 << 运算符

    //返回值作为左值,必须返回对象引用
    std::cout<<c1<<std::endl<<"链式编程"<<std::endl;
    //operator<<(std::cout,c1);
    //等价于 cout<<c1;

    system("pause");
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值