运算符函数的定义与其他函数的定义类似,惟一的区别是运算符函数的函数名是由关键字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=;
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);
} 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>)
cout<<"("<<real<<"+"<<imag<<"i)"<<endl;
else if(imag==)
cout<<"("<<real<<")"<<endl;
else
cout<<"("<<real<<"-"<<fabs(imag)<<"i)"<<endl;
} int main()
{
Complex c1(,),c2(,-),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 ;
}

友元函数运算符

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=;
imag=;
} Complex::Complex(double r)
{
real=r;
imag=;
} 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>)
cout<<"("<<real<<"+"<<imag<<"i)"<<endl;
else if(imag==)
cout<<"("<<real<<")"<<endl;
else
cout<<"("<<real<<"-"<<fabs(imag)<<"i)"<<endl;
} int main()
{
Complex c1(,),c;
c=c1+2.5;
cout<<"c1+2.5=";
c.display();
return ;
}
#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[][];
}; Matrix operator+(const Matrix &m1,const Matrix &m2)
{
Matrix m;
for(int i=;i<;i++)
for(int j=;j<;j++)
m.a[i][j]=m1.a[i][j]+m2.a[i][j]; return m;
} Matrix::Matrix()
{
for(int i=;i<;i++)
for(int j=;j<;j++)
{
a[i][j]=;
}
} void Matrix::SetValues()
{
srand((unsigned)time(NULL));
for(int i=;i<;i++)
for(int j=;j<;j++)
a[i][j]=rand()%max;
} ostream& operator<<(ostream &output,Matrix &m)
{
for(int i=;i<;i++)
{
for(int j=;j<;j++)
output<<setw()<<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 ;
}

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

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

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

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

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

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

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

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

c++重在运算符的更多相关文章

  1. c++重在运算符前置自增和后置自增

    class student { int age; }; int main() { class student stu; (stu++)++;//error ++(stu++);//error stu+ ...

  2. C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数

    (根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 对运算符重载的函数有两种处理方式:(1)把运算符 ...

  3. C++ Primer注意事项11_运算符重载_算术/关系运算符_下标运算符

    1.算术/关系运算符 平时,定义成非成员函数以同意左右側运算对象进行转换.由于这些运算符一般不须要改变运算对象的状态,所以形參都是常量的引用. 以"+"号运算符为例: Person ...

  4. RTTI之typeid运算符

    1 #include <iostream> 2 #include <cstdlib> 3 #include <ctime> 4 #include <typei ...

  5. shell运算符

    原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用. expr 是一款表达式计算工具,使用它能完成表达式的求值操作. #!/bin/bash v ...

  6. SQL Server-聚焦APPLY运算符(二十七)

    前言 其实有些新的特性在SQL Server早就已经出现过,但是若非系统的去学习数据库你会发现在实际项目中别人的SQL其实是比较复杂的,其实利用新的SQL Server语法会更加方便和简洁,从本节开始 ...

  7. java中的移位运算符:<<,>>,>>>总结

    java中有三种移位运算符 <<      :     左移运算符,num << 1,相当于num乘以2 >>      :     右移运算符,num >& ...

  8. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  9. .NET 基础 一步步 一幕幕[运算符、占位符、转义符]

      运算符.占位符.转义符 好吧,在五局全胜之后,终于升到了三个钻,距离一个星星还有一大段距离,忽然想起来今天的博客还没写,果断坑队友,来写博客了....感觉以后还是每天更新一篇比较好.要不晚上就该熬 ...

随机推荐

  1. poj1228稳定凸包

    就是给一系列点,看这是不是一个稳定凸包 稳定凸包是指一个凸包不能通过加点来使它扩大面积,也就是说每条边最少有三个点 判断的地方写错了,写了两边循环,其实数组s已经排好了序,直接每三个判断就好了 #in ...

  2. 重新学习MySQL数据库1:无废话MySQL入门

    重新学习Mysql数据库1:无废话MySQL入门 开始使用 我下面所有的SQL语句是基于MySQL 5.6+运行. MySQL 为关系型数据库(Relational Database Manageme ...

  3. 强连通分量算法-codevs1332

    解决有向图的强连通分量的算法,有两个,一个是tarjan,一个是kosaraju,上午只看了一下kosaraju,不算太难,理解之后写了个模板题. 先说kosaraju算法,算法的主要思路是进行两次d ...

  4. nyoj998——欧拉+折半查找

    Sum 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 给你一个数N,使得在1~N之间能够找到x使得x满足gcd( x ,  N  ) >= M, 求解gcd( ...

  5. mysql快问快答

    1.查看mysql版本 select version(); show variables like 'version'; 2.mysql 可以按timestamp排序吗? 可以 3.怎么查询商户下是否 ...

  6. Highcharts 基本条形图;Highcharts 堆叠条形图;Highcharts 反向条形图

    Highcharts 基本条形图 配置 chart 配置 设置 chart 的 type 属性 为 bar ,chart.type 描述了图表类型.默认值为 "line". var ...

  7. JS种正则表达式的基础用法

    基础语法 元字符 常用元字符 含义 . 匹配除换行符以外的任意字符 \w 匹配字母数字或下划线 \W 匹配不是字母.数字.下划线的字符 \d 匹配数字,相当于[0-9] \D 匹配不是数字的字符 \s ...

  8. 【zznu-2093】毁掉这颗二叉树

    题目描述 广寒宫下有株二叉树,树上共有n个节点,通过n-1条树枝连接,树下有一只玉兔,吴刚提着斧子站在一旁. 他恼恨一切同他争夺嫦娥的事物,所以他决定通过砍二叉树上的n-1条树枝来毁掉这颗二叉树. 妙 ...

  9. reactNative 的一些学习

    手把手视频 学习资料大全 入门系列

  10. OpenFlow技术白皮书-V1.0

    1.  概述 OpenFlow是由斯坦福大学的Nick McKeown教授在2008年4月ACM Communications Review上发表的一篇论文OpenFlow: enabling inn ...