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=;
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++重在运算符的更多相关文章
- c++重在运算符前置自增和后置自增
class student { int age; }; int main() { class student stu; (stu++)++;//error ++(stu++);//error stu+ ...
- C++学习之路—运算符重载(二)运算符重载作为类的成员函数和友元函数
(根据<C++程序设计>(谭浩强)整理,整理者:华科小涛,@http://www.cnblogs.com/hust-ghtao转载请注明) 对运算符重载的函数有两种处理方式:(1)把运算符 ...
- C++ Primer注意事项11_运算符重载_算术/关系运算符_下标运算符
1.算术/关系运算符 平时,定义成非成员函数以同意左右側运算对象进行转换.由于这些运算符一般不须要改变运算对象的状态,所以形參都是常量的引用. 以"+"号运算符为例: Person ...
- RTTI之typeid运算符
1 #include <iostream> 2 #include <cstdlib> 3 #include <ctime> 4 #include <typei ...
- shell运算符
原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用. expr 是一款表达式计算工具,使用它能完成表达式的求值操作. #!/bin/bash v ...
- SQL Server-聚焦APPLY运算符(二十七)
前言 其实有些新的特性在SQL Server早就已经出现过,但是若非系统的去学习数据库你会发现在实际项目中别人的SQL其实是比较复杂的,其实利用新的SQL Server语法会更加方便和简洁,从本节开始 ...
- java中的移位运算符:<<,>>,>>>总结
java中有三种移位运算符 << : 左移运算符,num << 1,相当于num乘以2 >> : 右移运算符,num >& ...
- 我的MYSQL学习心得(五) 运算符
我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...
- .NET 基础 一步步 一幕幕[运算符、占位符、转义符]
运算符.占位符.转义符 好吧,在五局全胜之后,终于升到了三个钻,距离一个星星还有一大段距离,忽然想起来今天的博客还没写,果断坑队友,来写博客了....感觉以后还是每天更新一篇比较好.要不晚上就该熬 ...
随机推荐
- Rem实现移动端适配
移动端适配 web页面跑在手机端(h5页面) 跨平台 基于webview() 基于webkit 常见适配方法 pc端采用display:inline-block,让div盒子横着排 移动web:采用定 ...
- 设计模式--策略模式C++实现
策略模式C++实现 1定义 (Strategy Pattern)定义一组算法,将每个算法都封装起来,并且使他们可以相互替换 也叫政策模式 2类图 3实现 class Strategy{ protect ...
- 重新学习MySQL数据库1:无废话MySQL入门
重新学习Mysql数据库1:无废话MySQL入门 开始使用 我下面所有的SQL语句是基于MySQL 5.6+运行. MySQL 为关系型数据库(Relational Database Manageme ...
- mysql中一个字段根据另一字段的值分割为不同列
1.数据结构如下: vehicleId mileage_type mileage 11AM6897 0 120 11AM6897 1 60 13AY9180 0 ...
- scrapy 6023 telnet查看爬虫引擎相关状态
Telnet终端(Telnet Console) Scrapy提供了内置的telnet终端,以供检查,控制Scrapy运行的进程. telnet仅仅是一个运行在Scrapy进程中的普通python终端 ...
- UML类图几种关系
(转自:http://www.open-open.com/lib/view/open1328059700311.html) 在UML类图中,常见的有以下几种关系: 泛化(Generalization) ...
- CSS样式--移动划过超链接鼠标变手型详解
用css控制鼠标样式的语法如下:<span style="cursor:*">文本或其它页面元素</span>把 * 换成如下15个效果的一种: 下面是对这 ...
- fzu Problem 2275 Game(kmp)
Problem 2275 Game Accept: 62 Submit: 165Time Limit: 1000 mSec Memory Limit : 262144 KB Proble ...
- tsl/ssl 证书制作记录
生成自签名证书 生成服务端秘钥 $ openssl genrsa -out server.key 1024 生成证书请求文件 编写配置文件openssl.cnf $ vi openssl.cnf [r ...
- jquery中ajax跨域的写法
由于JS同源策略的影响,因此js只能访问同域名下的文档.因此要实现跨域,一般有以下几个方法: 一.处理跨域的方式: 1.代理 2.XHR2 HTML5中提供的XMLHTTPREQUEST Level2 ...