操作符重载(下)

浪子不回头ぞ 提交于 2020-02-22 00:55:17

类的成员函数是否可以作为操作符重载的函数?

通过operator关键字能够将操作符定义为全局函数

操作符重载的本质就是函数重载

类的成员函数是否可以作为操作符重载的函数?

A:当然可以

#include <cstdlib>
#include <iostream>

using namespace std;

class Complex
{
    int a;
    int b;
public:
    Complex(int a, int b)
    {
        this->a = a;
        this->b = b;
    }       
    
    Complex operator+ (const Complex& c2); //成员函数:+操作符重载 
    									   //注意:此处有一个隐藏参数:this指针 
    
    friend ostream& operator<< (ostream& out, const Complex& c);
};

ostream& operator<< (ostream& out, const Complex& c)
{
    out<<c.a<<" + "<<c.b<<"i";
    
    return out;
}

Complex Complex::operator+ (const Complex& c2) //成员函数:+操作符重载 
											   //成员函数的操作符重载  比 全局函数的操作符重载 要 少一个参数,其实可以理解为this指针替代了 
{
    Complex ret(0, 0);
    
    ret.a = this->a + c2.a;
    ret.b = this->b + c2.b;
    
    return ret;
}

int main(int argc, char *argv[])
{
    Complex c1(1, 2);
    Complex c2(3, 4);
    Complex c3 = c1 + c2; //相当于 c1. operator+ (c2);
    
    cout<<c1<<endl;
    cout<<c2<<endl;
    cout<<c3<<endl;
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

在这里插入图片描述

用成员函数重载的操作符

比全局操作符重载函数少一个参数,即左操作数
不需要使用friend关键字

在这里插入图片描述

什么时候使用全局函数重载操作符?什么时候使用成员函数重载操作符?

当无法修改左操作数的类时,使用全局函数进行重载(例如:ostream的<<操作符,在标准库中,无法修改ostream类)

=, [], ()和->操作符只能通过成员函数进行重载

重载=, []操作符有什么用哪?

数组类的改进

重载[]操作符

int& operator[](int i);

int& Array::operator[](int i)
{
    return mSpace[i];
}

//调用
for(int i=0; i<a1.length(); i++) //赋值
{
    a1[i] = i + 1;
}

for(int i=0; i<a1.length(); i++) //取值
{
    printf("Element %d: %d\n", i, a1[i]);
}

重载=操作符

Array& operator= (const Array& obj);
 
Array& Array::operator= (const Array& obj) //返回引用Array&是为了支持 链式赋值 a1 = a1 = a3
{
    delete[] mSpace; //delete之前的内存
    
    mLength = obj.mLength;
    
    mSpace = new int[mLength]; //深拷贝    
    for(int i=0; i<mLength; i++)
    {
        mSpace[i] = obj.mSpace[i];
    }
    
    return *this;
}

//调用
Array a1(10);
Array a2(0);
Array a3(0);

a3 = a2 = a1;

重载=操作符

bool operator== (const Array& obj);

bool Array::operator== (const Array& obj)
{
    bool ret = true;
    
    if( mLength == obj.mLength )
    {
        for(int i=0; i<mLength; i++)
        {
            if( mSpace[i] != obj.mSpace[i] )
            {
                ret = false;
                break;
            }
        }
    }
    else
    {
        ret = false;
    }
    
    return ret;
}

//调用
if( a1 == a2 )
{
    printf("a1 == a2\n");
}

数组类:最终完整代码

Array.h


#ifndef _ARRAY_H_
#define _ARRAY_H_

class Array
{
private:
    int mLength;
    int* mSpace;

public:
    Array(int length);
    Array(const Array& obj);
    int length();
    ~Array();
    int& operator[](int i);
    Array& operator= (const Array& obj);
    bool operator== (const Array& obj);
    bool operator!= (const Array& obj);
};

#endif

Array.cpp

#include <stdio.h>
#include "Array.h"

Array::Array(int length)
{
    if( length < 0 )
    {
        length = 0;
    }
    
    mLength = length;
    mSpace = new int[mLength];
}

Array::Array(const Array& obj)
{
    mLength = obj.mLength;
    
    mSpace = new int[mLength];
    
    for(int i=0; i<mLength; i++)
    {
        mSpace[i] = obj.mSpace[i];
    }
}

int Array::length()
{
    return mLength;
}

Array::~Array()
{
    mLength = -1;
    printf("%08X\n", mSpace);
    delete[] mSpace;
}

int& Array::operator[](int i)
{
    return mSpace[i];
}

Array& Array::operator= (const Array& obj)
{
    delete[] mSpace;
    
    mLength = obj.mLength;
    
    mSpace = new int[mLength];
    
    for(int i=0; i<mLength; i++)
    {
        mSpace[i] = obj.mSpace[i];
    }
    
    return *this;
}

bool Array::operator== (const Array& obj)
{
    bool ret = true;
    
    if( mLength == obj.mLength )
    {
        for(int i=0; i<mLength; i++)
        {
            if( mSpace[i] != obj.mSpace[i] )
            {
                ret = false;
                break;
            }
        }
    }
    else
    {
        ret = false;
    }
    
    return ret;
}

bool Array::operator!= (const Array& obj)
{
    return !(*this == obj);
}

main.cpp

#include <stdio.h>
#include "Array.h"

int main()
{
    Array a1(10);
    Array a2(0);
    Array a3(0);
    
    if( a1 != a2 )
    {
        printf("a1 != a2\n");
    }
    
    for(int i=0; i<a1.length(); i++)
    {
        a1[i] = i + 1;
    }
    
    for(int i=0; i<a1.length(); i++)
    {
        printf("Element %d: %d\n", i, a1[i]);
    }
    
    a3 = a2 = a1;
    
    if( a1 == a2 )
    {
        printf("a1 == a2\n");
    }
    
    for(int i=0; i<a2.length(); i++)
    {
        printf("Element %d: %d\n", i, a2[i]);
    }
    
    printf("Press any key to continue...");
    getchar();
    return 0;
}

C++编译器会为每个类提供默认的赋值操作符=

C++编译器会为每个类提供默认的赋值操作符
默认的赋值操作符只是做简单的值复制
类中存在指针成员变量时就需要重载赋值操作符

++操作符重载

++操作符只有一个操作数
++操作符有前缀和有后缀的区分

问题:如何重载++操作符才能区分前置运算和后置运算?

操作符重载是通过函数重载实现的

​ C++中通过一个占位参数来区分前置运算和后置运算

部分代码

Complex operator++ (int); //obj++
Complex operator++ (); //++obj

Complex Complex::operator++ (int)
{
	Complex ret = *this; //记录一下当前的值
    
    a++;
    b++;
    
    return ret;
}


Complex Complex::operator++ ()
{
	++a;
    ++b;
    
    return *this;
}

全部代码:

#include <cstdlib>
#include <iostream>

using namespace std;

class Complex
{
    int a;
    int b;
public:
    Complex(int a, int b)
    {
        this->a = a;
        this->b = b;
    }
    
    int getA()
    {
        return a;
    }
    
    int getB()
    {
        return b;
    }
    
    Complex operator+ (const Complex& c2); 
    Complex operator++ (int);  //obj++
    Complex& operator++(); ++obj
    
    friend ostream& operator<< (ostream& out, const Complex& c);
};

ostream& operator<< (ostream& out, const Complex& c)
{
    out<<c.a<<" + "<<c.b<<"i";
    
    return out;
}

Complex Complex::operator++ (int)
{
    Complex ret = *this;
    
    a++;
    b++;
    
    return ret;
    
}

Complex& Complex::operator++()
{
    ++a;
    ++b;
    
    return *this;
}

Complex Complex::operator+ (const Complex& c2)
{
    Complex ret(0, 0);
    
    ret.a = this->a + c2.a;
    ret.b = this->b + c2.b;
    
    return ret;
}

int main(int argc, char *argv[])
{
    Complex c1(1, 2);
    Complex c2(3, 4);
    Complex c3 = c2;
    
    c2++;
    ++c3;
    
    cout<<c1<<endl;
    cout<<c2<<endl;
    cout<<c3<<endl;
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

不要重载&&和||,为什么?

#include <cstdlib>
#include <iostream>

using namespace std;

class Test
{
    int i;
public:
    Test(int i)
    {
        this->i = i;
    }
    
    Test operator+ (const Test& obj)
    {
        Test ret(0);
        
        cout<<"Test operator+ (const Test& obj)"<<endl;
        
        ret.i = i + obj.i;
        
        return ret;
    }
    
    bool operator&& (const Test& obj)
    {
        cout<<"bool operator&& (const Test& obj)"<<endl;
        
        return i && obj.i;
    }
};

int main(int argc, char *argv[])
{
    int a1 = 0;
    int a2 = 1;
    
    if( a1 && (a1 + a2) )
    {
        cout<<"Hello"<<endl;
    }
    
    Test t1 = 0;
    Test t2 = 1;
    
    if( t1 && (t1 + t2) ) //等价于 ti. operator&& (t1. operator+ (t2) ) 
    {
        cout<<"World"<<endl;
    }
    
    cout << "Press the enter key to continue ...";
    cin.get();
    return EXIT_SUCCESS;
}

在这里插入图片描述

&&和||是C++中非常特殊的操作符
&&和||内置实现了短路规则
操作符重载是靠函数重载来完成的
操作数作为函数参数传递
C++的函数参数都会被求值,无法实现短路规则

小结

操作符重载可以直接使用类的成员函数实现
=, [], ()和->操作符只能通过成员函数进行重载
++操作符通过一个int参数进行前置与后置的重载
C++中不要重载&&和||操作符

l;
}

Test t1 = 0;
Test t2 = 1;

if( t1 && (t1 + t2) ) //等价于 ti. operator&& (t1. operator+ (t2) ) 
{
    cout<<"World"<<endl;
}

cout << "Press the enter key to continue ...";
cin.get();
return EXIT_SUCCESS;

}


[外链图片转存中...(img-TfZ26E3v-1582292964940)]



&&和||是C++中非常特殊的操作符
	&&和||内置实现了短路规则
	操作符重载是靠函数重载来完成的
	操作数作为函数参数传递
	C++的函数参数都会被求值,无法实现短路规则



# 小结

操作符重载可以直接使用类的成员函数实现
=, [], ()和->操作符只能通过成员函数进行重载
++操作符通过一个int参数进行前置与后置的重载
C++中不要重载&&和||操作符





# 







































标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!