c++重在运算符

运算符函数的定义与其他函数的定义类似,惟一的区别是运算符函数的函数名是由关键字operator和其后要重载的运算符符号构成的。运算符函数定义的一般格式如下:

<返回类型说明符> operator <运算符符号>(<参数表>)
{
  //函数体  
}

运算符重载时要遵循以下规则:

   (1) 除了类属关系运算符"."、成员指针运算符".*"、作用域运算符"::"、sizeof运算符和三目运算符"?:"以外,C++中的所有运算符都可以重载。

(2) 重载运算符限制在C++语言中已有的运算符范围内的允许重载的运算符之中,不能创建新的运算符。

(3) 运算符重载实质上是函数重载,因此编译程序对运算符重载的选择,遵循函数重载的选择原则。

(4) 重载之后的运算符不能改变运算符的优先级和结合性,也不能改变运算符操作数的个数及语法结构。

(5) 运算符重载不能改变该运算符用于内部类型对象的含义。它只能和用户自定义类型的对象一起使用,或者用于用户自定义类型的对象和内部类型的对象混合使用时。

(6) 运算符重载是针对新类型数据的实际需要对原有运算符进行的适当的改造,重载的功能应当与原有功能相类似,避免没有目的地使用重载运算符。

 

  运算符函数重载一般有两种形式:重载为类的成员函数和重载为类的非成员函数。非成员函数通常是友元。(可以把一个运算符作为一个非成员、非友元函数重载。但是,这样的运算符函数访问类的私有和保护成员时,必须使用类的公有接口中提供的设置数据和读取数据的函数,调用这些函数时会降低性能。可以内联这些函数以提高性能。)   

重载为成员函数

 <函数类型> operator <运算符>(<参数表>)
 {
    //函数体

 }

当运算符重载为类的成员函数时,函数的参数个数比原来的操作数要少一个(后置单目运算符除外),这是因为成员函数用this指针隐式地访问了类的一个对象,它充当了运算符函数最左边的操作数。因此:

   (1) 双目运算符重载为类的成员函数时,函数只显式说明一个参数,该形参是运算符的右操作数。

(2) 前置单目运算符重载为类的成员函数时,不需要显式说明参数,即函数没有形参。

(3) 后置单目运算符重载为类的成员函数时,函数要带有一个整型形参。

    调用成员函数运算符的格式如下:

    <对象名>.operator <运算符>(<参数>)

    它等价于

    <对象名><运算符><参数>

    例如:a+b等价于a.operator +(b)。一般情况下,我们采用运算符的习惯表达方式。

#include <iostream>
#include <cmath>
using namespace std;
class Complex
{
    public:
        Complex();
        Complex(double r,double i);
        Complex operator+(Complex &c1);
        Complex operator-(Complex &c1);
        Complex operator*(Complex &c1);
        Complex operator/(Complex &c1);
        void display();
    private:
        double real;
        double imag;
};

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

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

Complex Complex::operator+(Complex &c1)
{
    return  Complex(real+c1.real,imag+c1.imag);
}

Complex Complex::operator-(Complex &c1)
{
    return Complex(real-c1.real,imag-c1.imag);
}

Complex Complex::operator*(Complex &c1)
{
    return Complex(real*c1.real+(-imag*c1.imag),real*c1.imag+imag*c1.real);
}

Complex Complex::operator/(Complex &c1)
{
    return Complex((real*c1.real+imag*c1.imag)/(c1.real*c1.real+c1.imag*c1.imag),
                    (imag*c1.real-real*c1.imag)/(c1.real*c1.real+c1.imag*c1.imag));
}

void Complex::display()
{
    if(imag>0)
        cout<<"("<<real<<"+"<<imag<<"i)"<<endl;
    else if(imag==0)
        cout<<"("<<real<<")"<<endl;
    else
        cout<<"("<<real<<"-"<<fabs(imag)<<"i)"<<endl;
}

int main() 
{
    Complex c1(1,2),c2(2,-2),c3,c4,c5,c6;
    c3=c1+c2;
    cout<<"c1=";
    c1.display();
    cout<<"c2=";
    c2.display();
    cout<<"c1+c2=";
    c3.display();
    c4=c1-c2;
    cout<<"c1-c2=";
    c4.display();
    c5=c1*c2;
    cout<<"c1*c2=";
    c5.display();
    c6=c1/c2;
    cout<<"c1/c2=";
    c6.display();
    return 0;
}

友元函数运算符

friend <函数类型> operator <运算符>(<参数表>)
{
     //函数体
}

当运算符重载为类的友元函数时,由于没有隐含的this指针,因此操作数的个数没有变化,所有的操作数都必须通过函数的形参进行传递,函数的参数与操作数自左至右一一对应。

operator <运算符>(<参数1>,<参数2>)

它等价于

<参数1><运算符><参数2>

例如:a+b等价于operator +(a,b)。
#include <iostream>
#include <cmath>
using namespace std;
class Complex 
{
    public:
        Complex();
        Complex(double r); 
        Complex(double r,double i);
        void display();
        friend Complex operator+(const Complex &c1,const Complex &c2);
    private:
        double real;
        double imag;
};

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

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

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

Complex operator+(const Complex &c1,const Complex &c2)
{
    return Complex(c1.real+c2.real,c1.imag+c2.imag);
}

void Complex::display()
{
    if(imag>0)
        cout<<"("<<real<<"+"<<imag<<"i)"<<endl;
    else if(imag==0)
        cout<<"("<<real<<")"<<endl;
    else
        cout<<"("<<real<<"-"<<fabs(imag)<<"i)"<<endl;
}

int main() 
{
    Complex c1(2,1),c;
    c=c1+2.5;
    cout<<"c1+2.5=";
    c.display();
    return 0;
}

 

#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#define max 100
using namespace std;

class Matrix
{
    public:
        Matrix();
        friend Matrix operator+(const Matrix &m1,const Matrix &m2);
        friend ostream& operator<<(ostream &output,Matrix &m);
        void SetValues();
    private:
        int a[2][3];    
}; 

Matrix operator+(const Matrix &m1,const Matrix &m2)
{
    Matrix m;
    for(int i=0;i<2;i++)
        for(int j=0;j<3;j++)
            m.a[i][j]=m1.a[i][j]+m2.a[i][j];
                
    return m;
}

Matrix::Matrix()
{
    for(int i=0;i<2;i++)
        for(int j=0;j<3;j++)
        {
            a[i][j]=0;
        }
}

void Matrix::SetValues()
{
    srand((unsigned)time(NULL));
    for(int i=0;i<2;i++)
        for(int j=0;j<3;j++)
            a[i][j]=rand()%max;
}

ostream& operator<<(ostream &output,Matrix &m)
{
    for(int i=0;i<2;i++)
    {
        for(int j=0;j<3;j++)
            output<<setw(6)<<m.a[i][j]<<" ";
    
        output<<endl;
    }
    output<<endl;
    return output;
}
int main()
{
    Matrix a,b,c;
    a.SetValues();
    b.SetValues();
    c=a+b;
    cout<<"a+b="<<endl;
    cout<<c<<endl;
    return 0;
}

  (1) 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。

(2) 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。

(3) 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。

(4) 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。

(5) 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。

(6) 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部类型的对象,该运算符函数必须作为一个友元函数来实现。

(7) 当需要重载运算符具有可交换性时,选择重载为友元函数。

另附一篇重载运算符讲解:https://www.cnblogs.com/zpcdbky/p/5027481.html

posted on 2018-10-13 14:00  tianzeng  阅读(478)  评论(0编辑  收藏  举报

导航