C++ 运算符重载

定义一个重载运算符的函数,在需要执行被重载的运算符的时候,系统会自动调用该函数,以实现相应的运算。

运算符重载是通过定义函数实现的,运算符重载实质上是函数的重载

语法格式:

函数类型 operator 运算符名称(形参列表)
{
    对运算符的重载处理
}

举个例子

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

小程序,复数计算器

传统方式实现:

#include <iostream>

class Complex
{
public:
    Complex();
    Complex(double r, double i);
    Complex complex_add(Complex &d);
    void print();

private:
    double real;
    double imag;
};

Complex::Complex()
{
    real = 0;
    imag = 0;
}

Complex ::Complex(double r, double i)
{
    real = r;
    imag = i;
}

Complex Complex::complex_add(Complex &d)
{
    Complex c;

    c.real = real + d.real;
    c.imag = imag + d.imag;

    return c;
}

void Complex::print()
{
    std::cout << "(" << real << ", " << imag << "i)\n";
}

int main()
{
    Complex c1(3, 4), c2(5, -10), c3;
    c3 = c1.complex_add(c2);
    std::cout << "c1 = ";
    c1.print();
    std::cout << "c2 = ";
    c2.print();
    std::cout << "c1 + c2 = ";
    c3.print();

    return 0;
}

通过重载运算符实现:

#include <iostream>

class Complex
{
public:
    Complex();
    Complex(double r, double i);
    Complex operator+(Complex &d);
    void print();

private:
    double real;
    double imag;
};

Complex::Complex()
{
    real = 0;
    imag = 0;
}

Complex ::Complex(double r, double i)
{
    real = r;
    imag = i;
}

Complex Complex::operator+(Complex &d)
{
    Complex c;
    c.real = real + d.real;
    c.imag = imag + d.imag;

    return c;
}

void Complex::print()
{
    std::cout << "(" << real << ", " << imag << "i)\n";
}

int main()
{
    Complex c1(3, 4), c2(5, -10), c3;
    c3 = c1 + c2;
    std::cout << "c1 = ";
    c1.print();
    std::cout << "c2 = ";
    c2.print();
    std::cout << "c1 + c2 = ";
    c3.print();

    return 0;
}

规则:

C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载

除了这些运算符不可以重载,其他运算符都可以重载:
    "." 成员访问运算符
    ".*" 成员指针访问运算符
    "::" 域运算符
    "sizeof" 尺寸运算符
    "?:" 条件运算符
重载不能改变运算符运算对象的个数, +号需要两个数相加,不能改变成一个数自己操作
重载不能改变运算符的优先级别,+还是加,不能变乘号
重载不能改变运算符的结合性
重载运算符的函数不能有默认的参数
重载运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应该有一个是类对象或类对象的引用。也就说不能全部都是C++标准类型。

刚才的例子中,运算符重载函数为什么只有一个参数?

其实实际上运算符重载函数有两个参数,但由于是重载函数是Complex类中的成员函数,有一个参数是隐式的,运算符重载函数是用this指针隐式地访问类对象的成员。

return Complex(real+c2.real, imag+c2.imag);
return Complex(this->real+c2.real, this->imag+c2.imag);
return Complex(c1.real+c2.real, c1.imag+c2.imag);

刚才都是把操作符重载函数放在类中,那么如果放在外面,也可以同样实现吗?

#include <iostream>

class Complex
{
public:
    Complex();
    Complex(double r, double i);
    friend Complex operator+(Complex &c, Complex &d);
    void print();

private:
    double real;
    double imag;
};

Complex::Complex()
{
    real = 0;
    imag = 0;
}

Complex::Complex(double r, double i)
{
    real = r;
    imag = i;
}

Complex operator+(Complex &c, Complex &d)
{
    Complex f;
    f.real = c.real + d.real;
    f.imag = c.imag + d.imag;

    return f;
}

void Complex::print()
{
    std::cout << "(" << real << ", " << imag << "i)\n";
}

int main()
{
    Complex c1(3, 4), c2(5, -10), c3;
    c3 = c1 + c2;
    std::cout << "c1 = ";
    c1.print();
    std::cout << "c2 = ";
    c2.print();
    std::cout << "c1 + c2 = ";
    c3.print();

    return 0;
}

运算符重载如果在类的外面,那就必须要把运算符函数作为友元函数,不然的话,就无法访问类中private里面的成员。

尽量避免友元函数,会破坏函数的封装

例题,实现重载运算符计算有理数的加减乘除

#include <iostream>
#include <string>
#include <cstdlib>

class Rational
{
public:
    Rational();
    Rational(int numerator, int denominator);
    Rational operator+(Rational rhs);
    Rational operator-(Rational rhs);
    Rational operator*(Rational rhs);
    Rational operator/(Rational rhs);

    void print();

private:
    void normalize();

    int numerator;
    int denominator;
};

Rational::Rational()
{
    numerator = 0;
    denominator = 0;
}

Rational::Rational(int numerator, int denominator)
{
    this->numerator = numerator;
    this->denominator = denominator;
}

void Rational::normalize()
{
    if(denominator < 0)
    {
        numerator = -numerator;
        denominator = -denominator;
    }

    int a = abs(numerator);
    int b = abs(denominator);

    while(b>0)
    {
        int t = a % b;
        a = b;
        b = t;
    }

    numerator /= a;
    denominator /= a;
}

Rational Rational::operator+(Rational rhs)
{
    Rational r;
    r.numerator = numerator*denominator + rhs.numerator*rhs.denominator;
    r.denominator = denominator * rhs.denominator;
    r.normalize();
    return r;
}

Rational Rational::operator-(Rational rhs)
{
    rhs.numerator = -rhs.numerator;
    return operator+(rhs);
}

Rational Rational::operator*(Rational rhs)
{
    Rational r;
    r.numerator = numerator * rhs.numerator;
    r.denominator = denominator * rhs.denominator;
    r.normalize();
    return r;
}

Rational Rational::operator/(Rational rhs)
{
    Rational r;
    r.numerator = numerator * rhs.denominator;
    r.denominator = denominator * rhs.numerator;
    r.normalize();
    return r;
}

void Rational::print()
{
    if (numerator % denominator == 0)
    {
        std::cout << numerator / denominator;
    }
    else
    {
        std::cout << numerator << " / " << denominator;
    }
}

int main()
{
    Rational r1(1, 4);
    Rational r2(1, 4);

    Rational result = r1 + r2;
    r1.print();
    std::cout << " + ";
    r2.print();
    std::cout << " = ";

    result.print();
    std::cout << "\n";

    result = r1 - r2;
    r1.print();
    std::cout << " - ";
    r2.print();
    std::cout << " = ";
    result.print();
    std::cout << "\n";

    result = r1 * r2;
    r1.print();
    std::cout << " * ";
    r2.print();
    std::cout << " = ";
    result.print();
    std::cout << "\n";

    result = r1 / r2;
    r1.print();
    std::cout << " / ";
    r2.print();
    std::cout << " = ";
    result.print();
    std::cout << "\n";

    return 0;
}

重载左移操作符 <<

std::cout << "Hello World" << std::endl;

C标准库对左移操作符 (<<)进行了重载,让它可以把值发送到一个流去。

原型:std::ostream& operator<<( std::ostream& os, Rational f );

第一个参数os是将要向它写数据的那个流,它是以引用传递方式传递的。

第二个参数是打算写到那个流里的数据值,不同的operator<<( ) 重载函数就是因为这个输入参数才相互区别的。

#include <iostream>
using namespace std;
class complex{
public:
    complex(double real = 0.0, double imag = 0.0): m_real(real), m_imag(imag){ };
public:
    friend complex operator+(const complex & A, const complex & B);
    friend complex operator-(const complex & A, const complex & B);
    friend complex operator*(const complex & A, const complex & B);
    friend complex operator/(const complex & A, const complex & B);
    friend istream & operator>>(istream & in, complex & A);
    friend ostream & operator<<(ostream & out, complex & A);
private:
    double m_real;  //实部
    double m_imag;  //虚部
};
//重载加法运算符
complex operator+(const complex & A, const complex &B){
    complex C;
    C.m_real = A.m_real + B.m_real;
    C.m_imag = A.m_imag + B.m_imag;
    return C;
}
//重载减法运算符
complex operator-(const complex & A, const complex &B){
    complex C;
    C.m_real = A.m_real - B.m_real;
    C.m_imag = A.m_imag - B.m_imag;
    return C;
}
//重载乘法运算符
complex operator*(const complex & A, const complex &B){
    complex C;
    C.m_real = A.m_real * B.m_real - A.m_imag * B.m_imag;
    C.m_imag = A.m_imag * B.m_real + A.m_real * B.m_imag;
    return C;
}
//重载除法运算符
complex operator/(const complex & A, const complex & B){
    complex C;
    double square = A.m_real * A.m_real + A.m_imag * A.m_imag;
    C.m_real = (A.m_real * B.m_real + A.m_imag * B.m_imag)/square;
    C.m_imag = (A.m_imag * B.m_real - A.m_real * B.m_imag)/square;
    return C;
}
//重载输入运算符
istream & operator>>(istream & in, complex & A){
    in >> A.m_real >> A.m_imag;
    return in;
}
//重载输出运算符
ostream & operator<<(ostream & out, complex & A){
    out << A.m_real <<" + "<< A.m_imag <<" i ";;
    return out;
}
int main(){
    complex c1, c2, c3;
    cin>>c1>>c2;
    c3 = c1 + c2;
    cout<<"c1 + c2 = "<<c3<<endl;
    c3 = c1 - c2;
    cout<<"c1 - c2 = "<<c3<<endl;
    c3 = c1 * c2;
    cout<<"c1 * c2 = "<<c3<<endl;
    c3 = c1 / c2;
    cout<<"c1 / c2 = "<<c3<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值