运算符重载

本文详细介绍了C++中运算符重载的实现,包括自定义类Int的操作符重载,如加法、取地址、比较等,并扩展到复数类Complex的相加运算符重载。此外,还探讨了括号运算符重载和含指针成员对象的运算符重载,以及输出流重载在String类中的应用。
摘要由CSDN通过智能技术生成

由于语法规定,不能以运算符来作为函数名,因此C++中规定以operator+符号作为函数名来实现运算。

普通运算符重载

要求:自定义类实现常见的运算符重载

#include<iostream>
using namespace std;
​
class Int
{
    int value;
public:
    Int(int x = 0)
        :value(x) {}
    Int(const Int& src)
        :value(src.value) {}
    Int& operator=(const Int& src)//等号运算符重载
    {
        if (this != &src)
        {
            value = src.value;
            return *this;
        }
    }
    ~Int() {}
    Int* operator&(){return this;}//取地址重载
​
    const Int* operator&()const { return this; }//对常量的取地址重载
    //前置加加重载:先加在返回,代价小
    Int& operator++()
    {
        value += 1;
        return*this;
    }
    //后置加 :int 只是用来标记区分前置后置加加,无实际作用,代价大
    Int operator++(int)//先返回在加
    {
        Int old = *this;//先保存值用于返回
        ++* this;//调用前置加加
        return old;//返回旧值
    }
    Int operator+(const Int& src)const//对象与对象加
    {
        return Int(value + src.value);
    }
    Int operator+(const int num)const//对象与常数相加
    {
        return Int(value + num);
    }
    Int& operator+=(const int& src)//加等运算符重载
    {
        this->value+=src.value;
        return *this;
    }
    bool operator==(const Int& src)const//  ==运算符重载 
    {
        return value == src.value;
    }
    bool operator!=(const Int& src)const// !=运算符重载
    {
        return !((*this)== src);//调用 ==运算都重载
    }
    bool operator<(const Int& src)const// <运算符重载
    {
        return value < src.value;
    }
    bool operator>=(const Int& src)const // >=运算符重载
    {
        return !(*this < src.value);
    }
    bool operator>(const Int& src)const//  >运算符重载
    {
        return value > src.value;
    }
    bool operator<=(const Int& src)const// <=运算符重载
    {
        return !(*this > src.value);
    }
    operator int()const// 整形强转运算符,可将设计的类型中的某值转为内置类型,*this的类型没变。
    {
        return value;
    }
};
​
Int operator+(const int x, const Int& src)//常数与对象相加,由于参数的限制因此设置为全局函数
{
    return src + x;//调用对象与常数相加
}
​
int main()
{
    Int a(10), b(0), c(0);
    c = a + b;
    c = a + 10;
    c = 10 + a;
    b = ++a;
    //b=a.operator++();
    //b=operator(&a);
    c = a++;
    //c=a.operator++(0);
    //c=operator(&a,0);
    return 0;
}

注:

  • 自定义类型中的前置加加与优先级无关,把它函数当作函数看待。

  • 如果运算符重载的返回值是它本身时,以引用返回。

  • 如果返回值是一个将亡值或临时量时,以值返回

  • 内置类型需要转化为设计的类型时,由构造函数来进行转换:分显示转换和隐式转换。

  • 设计的类型需要转换为内置类型时,需要调用强转运算符重载。

相加运算符重载

要求实现add

括号运算符重载()

class Add
{
    mutable int value;//mutable 易变关键字,使value 在常对象中也可改
public:
​
    Add(int x=0):value(x){}
    int operator()(int a, int b)const//括号运算符重载 
    {
        value = a + b;
        return value;
    }
};
​
int main()
{
    int a = 10, b = 20, c = 0,d=0;
    Add add;
    c = add(a, b);//仿函数,add是对象,调用括号运算符重载
    d = Add()(a, b);//构造一个临时量调用括号运算符重载
    //c= add.operator()(a,b);
    return 0;
}

要求:设计一个复数的类,进行复数相加运算符重载

#include<iostream>
using namespace std;
class Complex
{
private:
    double Real, Image;
public:
    Complex():Real(0),Image(0){}
    Complex(double r,double i)
        :Real(r),Image(i){}
    Complex operator+(const Complex& c)const //加号运算符重载 
                                              //参数:const Complex *const this ,const Complex &c
    {
        return  Complex(Real + c.Real, Image + c.Image);//调用构造返回,无名构造,系统识别优化会
                                                        //直接将其当作将亡值构造在main的栈区
​
                     //Complex & Add(const Complex& c)const 如果返回值是引用,会在函数栈区构建一个对象,
    }                //将对象的地址返回,但是当函数栈帧退出,该地址失效,存在风险,不允许返回引用
    void Show()const 
    {
        cout << Real << "+" << Image << "i" << endl;
    }
};
int main()
{
    Complex c1(1.2, 2.3);
    Complex c2(3.4, 4.5);
    Complex x = c1 + c2;
    //相当于 :c3=c1.operator+(c2);
    //c3=operator+(&c1,c2)
    x.Show();
}

含指针成员对象运算符重载

  • *运算符重载 :返回所指向的内存

  • ->运算符重载:返回指针本身

#include<iostream>
using namespace std;
​
class Object
{
    int* ip;
public:
    Object(int* s = NULL) :ip(s)
    {
    }
    ~Object()
    {
        if (ip != NULL)
        {
            delete ip;
        }
        ip = NULL;
    }
    int& operator*()//*运算符重载,返回指针的指向
    {
        return *ip;
    }
    const int& operator*()const//常方法
    {
        return *ip;
    }
    int* operator->()//->运算符重载,返回指针本身
    {
        return ip;
        //return &**this  //即 *this 调用 *运算符重载得到指针的指向 在进行取地址。
    }
    const int* operator->()const//常方法
    {
        return ip;
        //return &**this;
    }
};

输出流重载

例:进行字符串的类设计

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string.h>
using namespace std;
class String
{
    char* str;
    String(char* p, int)//在加重载时,return时直接调用该构造,复制完后自动析构,回收p空间,防止内存泄漏
                        //int 用于标识区分公有的构造函数,达到重载效果
    {
        str = p;
    }
public:
    String(const char* p = NULL) :str(NULL)
    {
        if (p != NULL)
        {
            str = new char[strlen(p) + 1];
            strcpy_s(str,strlen(p)+1, p);
        }
        else//用来解决当构造对象时是缺省构造时:str=NULL,在赋值如果用来赋值的对象的str==NULL,就会造成系统崩溃
        {
            str = new char[1];//保证str至少在堆区开辟了一个字节的大小。
            *str = '\0';
        }
    }
    String(const String& src):str(NULL)
    {
        str = new char[strlen(src.str )+1 ];
        strcpy_s(str, strlen(src.str)+1, src.str);
    }
    String& operator=(const String& src)
    {
        if (this != &src)
        {
            delete[] str;
            str = new char[strlen(src.str )+1];
            strcpy_s(str, strlen(src.str )+1, src.str);
        }
        return *this;
    }
    ~String()
    {
        if (str != NULL)
        {
            delete[]str;
        }
        str = NULL;
    }
    ostream& operator<<(ostream& out)const//输出流重载
        //ostream& operator<<(const String* const this,ostream& out);
    {
        if (str != NULL)
        {
            out << str;
        }
        return out;
    }
    String operator+(const String& src)const 
    {
        char* p = new char[strlen(this->str) + strlen(src.str) + 1];
        strcpy(p, this->str);
        strcat(p, src.str);
        return String(p,1);//调用了特殊的私有构造,减小了时间消耗,防止了内存泄漏
    }
    String operator+(const char* s)const
    {
        char* p = new char[strlen(this->str) + strlen(s) + 1];
        strcpy(p, this->str);
        strcat(p, s);
        return String(p, 1);//调用了特殊的私有构造,减小了时间消耗,防止了内存泄漏
​
        //return *this+String(s)//不建议用,有对于的临时量被构建,时间消耗高
    }
​
};
String operator+(const char* s, const String& src)
{
    return String(s)+src;
}
ostream& operator<<(ostream& out, const String& s)//反转输出流重载,不加const:由于括号后的const只能加在this指针
{
    s << out;//调用输出流重载
    s<<cout;
    //s.operator<<(cout);
    //operator(&s,cout);
    return out;
}
int main()
{
    String s1("hello");
    s1 << cout;
    //s1<<cout;
    //s1.operator<<(cout);
    //operator(&s1,cout);
    cout << s1 << endl;
    //operator<<(cout,s1)
    //进入全局函数调用类内输出流重载
    String s2(s1);
    String s3;
    s1 = s3;
    cout << s2 << " " << s1 << endl;
    s1 = "lcx";
    String s4("lcx");
    s2 = s1 + s4;
    cout << s2 << endl;
    s2 = s1 + "hello";
    cout << s2 << endl;
    s2 = "lcx" + s1;
    cout << s2 << endl; 
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值