JHHK

欢迎来到我的个人网站
行者常至 为者常成

14、运算符重载、仿函数(函数对象)

目录

运算符重载一

LCPoint.hpp

#ifndef LCPoint_hpp
#define LCPoint_hpp

#include <stdio.h>
#include <iostream>

using namespace std;


class LCPoint{
    friend ostream &operator<<(ostream &,const LCPoint &);
public:
    int m_x;
    int m_y;
    LCPoint(int x,int y);
    
    //+ - * / 运算符重载
    const LCPoint operator+(const LCPoint &point) const;
    const LCPoint operator-(const LCPoint &point) const;
    const LCPoint operator*(const LCPoint &point) const;
    const LCPoint operator/(const LCPoint &point) const;
    const LCPoint operator-() const;//重载负号运算符,注意与减号的区别

    
    //+= -= *= /= 运算符重载
    LCPoint& operator+=(const LCPoint &point);
    LCPoint& operator-=(const LCPoint &point);
    LCPoint& operator*=(const LCPoint &point);
    LCPoint& operator/=(const LCPoint &point);
    
    
    //前++ 前--运算符重载
    LCPoint& operator++();
    LCPoint& operator--();
    //后++ 后--运算符重载
    const LCPoint operator++(int);
    const LCPoint operator--(int);
    
    
    //== !=运算符重载
    bool operator==(const LCPoint& point)const;
    bool operator!=(const LCPoint& point)const;

};

#endif /* LCPoint_hpp */

LCPoint.cpp

#include "LCPoint.hpp"

//构造函数实现
LCPoint::LCPoint(int x,int y):m_x(x),m_y(y){}


/**
 一、
 + - * / 运算符重载
 
 
 为什么用const修饰?
 
 第一个const,返回值
 比如:int a = 10;int b = 20; int c = ((a+b) = 40);
 正常的加号运算符的运算结果是不允许再次赋值40的。
 LCPoint的加号运算符重载后返回的是一个LCPoint对象是可以再次赋值的,所以返回值使用const修饰,避免再次赋值
 
 第二个const,参数
 对象作为参数时会调用拷贝构造函数产生中间对象增加调用开销,所以使用引用
 参数使用const修饰,保护变量内部不允许修改,使用const接收的参数范围更广,const 非const都可以接收
 
 第三个const,const成员函数
 内部不能修改非static成员变量,保护成员变量
 */
const LCPoint LCPoint::operator+(const LCPoint &point) const{
    return LCPoint(this->m_x+point.m_x,this->m_y+point.m_y);
}

const LCPoint LCPoint::operator-(const LCPoint &point) const{
    return LCPoint(this->m_x-point.m_x,this->m_y-point.m_y);
}

const LCPoint LCPoint::operator*(const LCPoint &point) const{
    return LCPoint(this->m_x*point.m_x,this->m_y*point.m_y);
}

const LCPoint LCPoint::operator/(const LCPoint &point) const{
    return LCPoint(this->m_x/point.m_x,this->m_y/point.m_y);
}

const LCPoint LCPoint::operator-() const{
    return LCPoint(-this->m_x,-this->m_y);
}




/**
 二、
 += -= *= /= 运算符重载
 
 第一:返回值为什么不用const进行修饰?
 int a = 10;int b = 20;int c = ((a+=b)=40);
 a+=b;相当于 a = a+b; 其最终是变量a,是可以再次赋值的。所以不用const修饰
 
 第二:函数为什么不用const修饰
 const修饰的函数内部不允许访问非static得成员变量。
 this->m_x += point.m_x;需要修改,所以不能使用const修饰函数
 
 第三:返回值为什么用引用
 1、因为返回的是自身
 2、使用引用避免产生中间变量
 */
LCPoint& LCPoint::operator+=(const LCPoint &point){
    this->m_x += point.m_x;
    this->m_y += point.m_y;
    return *this;
}

LCPoint& LCPoint::operator-=(const LCPoint &point){
    this->m_x -= point.m_x;
    this->m_y -= point.m_y;
    return *this;
    
}

LCPoint& LCPoint::operator*=(const LCPoint &point){
    this->m_x *= point.m_x;
    this->m_y *= point.m_y;
    return *this;
    
}

LCPoint& LCPoint::operator/=(const LCPoint &point){
    this->m_x /= point.m_x;
    this->m_y /= point.m_y;
    return *this;
}


/**
 三、
 前++ 前--运算符重载
 int a = 10;++a;相当于
 a = a+1;使用变量a;
 最终的结果是变量a;是可以赋值的所以使用引用返回自身
 
 
 后++ 后--运算符重载
 int a = 10; a++;相当于
 使用变量a;a+1;
 最终的结果是一个值,并不是变量a,所以使用const
 */
LCPoint& LCPoint::operator++(){
    this->m_x++;
    this->m_y++;
    return *this;
}

LCPoint&  LCPoint::operator--(){
    this->m_x--;
    this->m_y--;
    return *this;
}

const LCPoint  LCPoint::operator++(int){
//    LCPoint point(this->m_x,this->m_y);//调用构造函数
    LCPoint point(*this);//调用拷贝构造函数
    this->m_x++;
    this->m_y++;
    return point;
}

const LCPoint  LCPoint::operator--(int){
//    LCPoint point(this->m_x,this->m_y);
    LCPoint point(*this);
    this->m_x--;
    this->m_y--;
    return point;
}



//== !=运算符重载
bool LCPoint::operator==(const LCPoint& point)const{
    return this->m_x == point.m_x && this->m_y == point.m_y;
}

bool  LCPoint::operator!=(const LCPoint& point)const{
     return this->m_x != point.m_x || this->m_y != point.m_y;
}


//运算符重载(相当于OC的description函数)
ostream & operator<<(ostream &cout, const LCPoint &point) {
    return cout << "(" << point.m_x << ", " << point.m_y << ")";
}

调用测试

//全局函数、成员函数都支持运算符重载

void operatorTest(){
    LCPoint point1(10,20),point2(1,2);

    LCPoint point3 = point1+point2;
    cout<<"point3.m_x = "<<point3.m_x<<endl<<"point3.m_y = "<<point3.m_y<<endl;
    
    LCPoint point4 = point1-point2;
    cout<<"point4.m_x = "<<point4.m_x<<endl<<"point4.m_y = "<<point4.m_y<<endl;

    LCPoint point5 = point1*point2;
    cout<<"point5.m_x = "<<point5.m_x<<endl<<"point5.m_y = "<<point5.m_y<<endl;

    LCPoint point6 = point1/point2;
    cout<<"point6.m_x = "<<point6.m_x<<endl<<"point6.m_y = "<<point6.m_y<<endl;

    cout<<"------------------------------"<<endl;
    
    point1+=point2;
    cout<<"point1.m_x = "<<point1.m_x<<endl<<"point1.m_y = "<<point1.m_y<<endl;

    point1-=point2;
    cout<<"point1.m_x = "<<point1.m_x<<endl<<"point1.m_y = "<<point1.m_y<<endl;

    point1*=point2;
    cout<<"point1.m_x = "<<point1.m_x<<endl<<"point1.m_y = "<<point1.m_y<<endl;

    point1/=point2;
    cout<<"point1.m_x = "<<point1.m_x<<endl<<"point1.m_y = "<<point1.m_y<<endl;

    
    cout<<"------------------------------"<<endl;
    
    LCPoint point7 = ++point1;
    cout<<"point1.m_x = "<<point1.m_x<<endl<<"point1.m_y = "<<point1.m_y<<endl;
    cout<<"point7.m_x = "<<point7.m_x<<endl<<"point7.m_y = "<<point7.m_y<<endl;

    LCPoint point8 = --point1;
    cout<<"point1.m_x = "<<point1.m_x<<endl<<"point1.m_y = "<<point1.m_y<<endl;
    cout<<"point8.m_x = "<<point8.m_x<<endl<<"point8.m_y = "<<point8.m_y<<endl;
    
    LCPoint point9 = point1++;
    cout<<"point1.m_x = "<<point1.m_x<<endl<<"point1.m_y = "<<point1.m_y<<endl;
    cout<<"point9.m_x = "<<point9.m_x<<endl<<"point9.m_y = "<<point9.m_y<<endl;

    LCPoint point10 = point1--;
    cout<<"point1.m_x = "<<point1.m_x<<endl<<"point1.m_y = "<<point1.m_y<<endl;
    cout<<"point10.m_x = "<<point10.m_x<<endl<<"point10.m_y = "<<point10.m_y<<endl;
    
    cout<<"------------------------------"<<endl;
    
    bool isEqual = point1 == point3;
    bool isNotEqaul = point1 !=point3;
    cout<<"isEqual = "<<isEqual<<endl<<"isNotEqual = "<<isNotEqaul<<endl;
    
    
    cout<<"------------------------------"<<endl;

    cout<<point3<<endl;

}

运算符重载二

LCString.hpp

#ifndef LCString_hpp
#define LCString_hpp

#include <stdio.h>
#include <iostream>
using namespace std;
class LCString{
    friend ostream& operator<<(ostream& cout,LCString& string);
public:
    LCString(const char* cstring);//构造函数
    LCString(const LCString& string);//拷贝构造函数
    ~LCString();
    
    LCString& operator= (const char* cstring);
    LCString& operator= (const LCString& string);
    LCString  operator+ (const char* cstring);
    LCString  operator+ (const LCString& string);
    LCString& operator+=(const char* cstring);
    LCString& operator+=(const LCString& string);
    
    bool operator>(const char*cstring);
    bool operator>(const LCString& string);
    
    char operator[](int index);

    
private:
    char* m_cstring = nullptr;//用来接收字符串(指针一定要初始化,否则会指向不确定的内存,导致程序出错)
    LCString& assign(const char* cstring);
    char* join(const char* cstring1,const char* cstring2);

};


#endif /* LCString_hpp */

LCString.cpp

#include "LCString.hpp"


LCString::LCString(const char* cstring){
     
//    if (!cstring) {return;}
//    this->m_cstring = new char[strlen(cstring)+1]{};
//    strcpy(this->m_cstring, cstring);
    
    assign(cstring);
}

LCString::LCString(const LCString& string){
    
    assign(string.m_cstring);
}

LCString::~LCString(){
//    if (this->m_cstring) {
//        delete [] this->m_cstring;
//        this->m_cstring = nullptr;
//    }
    
    assign(nullptr);
}





LCString& LCString::operator=(const char *cstring){
    return  assign(cstring);
}


LCString& LCString::operator=(const LCString &string){
    return  assign(string.m_cstring);
}


LCString LCString::operator+(const char *cstring){
    LCString str(nullptr);
    char* newCString = join(this->m_cstring, cstring);
    if (newCString) {
        str.assign(newCString);
    }
    return str;
}

LCString LCString::operator+(const LCString &string){
    return operator+(string.m_cstring);
}


LCString& LCString::operator+=(const char* cstring){
    LCString str(nullptr);
    
    char* newCString = join(this->m_cstring, cstring);
    
    if (newCString) {
        assign(newCString);
    }
    
    return *this;
}

LCString& LCString::operator+=(const LCString& string){
    return operator+=(string.m_cstring);
}


bool  LCString::operator>(const char*cstring){
    
    if (!this->m_cstring || !cstring) {return 0;}
    
    return strcmp(this->m_cstring, cstring)>0;
}

bool  LCString::operator>(const LCString& string){
    return operator>(string.m_cstring);
}


char LCString::operator[](int index){
    
    if (!this->m_cstring || index<0 || index>=strlen(this->m_cstring)) {return '\0';}
    
    return this->m_cstring[index];
}








ostream& operator<<(ostream& cout,LCString& string){
    if (!string.m_cstring) {return cout;}
    return cout << string.m_cstring;
}


#pragma mark - private

LCString& LCString::assign(const char *cstring){
    
    //指向一样的堆空间
    if (this->m_cstring == cstring) {
        return *this;
    }
    
    
    //释放原有空间
    if (this->m_cstring) {
        delete [] this->m_cstring;
        this->m_cstring = nullptr;
    }
    
    
    //赋值新值
    if (cstring) {
        this->m_cstring = new char[strlen(cstring)+1]{};
        strcpy(this->m_cstring, cstring);
    }
    
    return *this;
}


char * LCString::join(const char* cstring1,const char* cstring2){
    
    if (!cstring1 || !cstring2) {return nullptr;}
    
    char* newCString = new char[strlen(cstring1)+strlen(cstring2)+1]{};
    
    strcat(newCString, cstring1);
    strcat(newCString, cstring2);
    
    return newCString;
}

调用测试

void operatorTest2(){
    LCString string("this is good !");
    LCString string2 = string;
    cout<<"string = "<<string<<endl<<"string2 = "<<string2<<endl;
    
    cout<<"---------------"<<endl;
    
    LCString string3 = string + string2;
    cout<<"string = "<<string<<endl<<"string2 = "<<string2<<endl<<"string3 = "<<string3<<endl;
    
    cout<<"---------------"<<endl;

    LCString string4 = string+=string2;
    cout<<"string = "<<string<<endl<<"string2 = "<<string2<<endl<<"string4 = "<<string4<<endl;
    
    
    cout<<"---------------"<<endl;

    bool isBig = string>string2;
    cout<<"isBig = "<<isBig<<endl;
    
    
    cout<<"---------------"<<endl;

    char c = string[2];
    cout<<"c = "<<c<<endl;
}

运算符重载注意点
有些运算符不可以被重载,比如
对象成员访问运算符:.
域运算符:::
三目运算符:?:
sizeof

有些运算符只能重载为成员函数,比如
赋值运算符:=
下标运算符:[ ]
函数运算符:( )
指针访问成员:->

单例模式补充

LCRocket.hpp

#ifndef LCRocket_hpp
#define LCRocket_hpp

#include <stdio.h>
#include <iostream>

using namespace std;

class LCRocket{
public:
    static LCRocket* shareRocket();
    static void deleteRocket();
    
private:
    static LCRocket* m_rocket;
    LCRocket(){}//外部禁止调用构造函数
    LCRocket(const LCRocket& rocket);//外部禁止调用拷贝构造函数
    void operator=(const LCRocket& rocket){};//外部禁止赋值行为
};


#endif /* LCRocket_hpp */

LCRocket.cpp

#include "LCRocket.hpp"

//初始化静态变量
LCRocket* LCRocket::m_rocket = nullptr;

LCRocket* LCRocket::shareRocket(){
    if (!m_rocket) {m_rocket = new LCRocket();}
    return m_rocket;
}

void LCRocket::deleteRocket(){
    if (m_rocket) {
        delete m_rocket;
        m_rocket = nullptr;
    }
}

调用测试

void shareRocketTest(){
    LCRocket * rocketPoint1 = LCRocket::shareRocket();
    LCRocket * rocketPoint2 = LCRocket::shareRocket();
    
    //rocketPoint1 = 0x1006758f0
    //rocketPoint2 = 0x1006758f0
    cout<<"rocketPoint1 = "<<rocketPoint1<<endl<<"rocketPoint2 = "<<rocketPoint2<<endl;
    
    //PS:一定要搞清楚指针和对象的区别
    LCRocket::deleteRocket();//释放的是堆空间的对象,但指针变量扔指向那块堆内存
    cout<<"rocketPoint1 = "<<rocketPoint1<<endl<<"rocketPoint2 = "<<rocketPoint2<<endl;
    rocketPoint2 = nullptr;//清除指针的指向
    rocketPoint2 = nullptr;
    cout<<"rocketPoint1 = "<<rocketPoint1<<endl<<"rocketPoint2 = "<<rocketPoint2<<endl;
    
    
    
    //构造函数已经私有化,禁止调用
    //Calling a private constructor of class 'LCRocket'
    //LCRocket rocket1 = LCRocket();
    
    //拷贝构造函数已经私有化,禁止调用
    //Calling a private constructor of class 'LCRocket'
    //LCRocket rocket2 = LCRocket(*rocketPoint1);
    //LCRocket rocket3 = *rocketPoint2;
    

    //赋值操作符重载后已经私有化,禁止调用
    //'operator=' is a private member of 'LCRocket'
    //*rocketPoint1 = *LCRocket::shareRocket();
}

仿函数

/**
 将一个对象当作一个函数一样来使用
 对比普通函数,它作为对象可以保存状态
 */
class Sum{
public:
    int operator()(int a,int b);
};


int Sum::operator()(int a, int b){
    return a+b;
}

void likeFuncTest(){
    Sum sum;
    
    int a = sum(1,2);
    
    cout<<"a = "<<a<<endl;
    
}

行者常至,为者常成!





R
Valine - A simple comment system based on Leancloud.