C++运算符_菜鸟教程
C++内置了多种运算符,支持基本数据类型运算,其中的部分运算符已针对不同操作数类型进行了重载
将这些运算符用于自定义类型时,可进行运算符重载
运算符重载只是一种 “ 语法上的方便 ” ,也就是说这是另一种函数调用方式
基本语法
定义重载的运算符(可视为特殊函数)就像定义(全局或类的成员)函数一样,有一个小小的区别是函数的名称:
operator@
其中operator是关键字,@是被重载的运算符,如:
HugeInt operator+(const HugeInt &A);
重载运算符的限制
- 并不是所有的运算符都支持重载:
简单解释一下->*
和 .*
class Fred{...};
typedef int (Fred::*FredMemFn)(int i, double d);
// use a typedef!!! please!!!
void sample(Fred x, Fred& y, Fred* z, FredMemFn func)
{
x.*func(42, 3.14);
y.*func(42, 3.14);
z->*func(42, 3.14);
}
typedef char (*PTRFUN)(int);
PTRFUN pFun;
char glFun(int a){ return;}
void main()
{
pFun = glFun;
(*pFun)(2);
}
解释:
typedef的功能是定义新的类型。
第一句定义了一种PTRFUN类型,并定义这种类型为指向某种函数的指针,该函数以一个int为参数并返回char类型。后面就可以像使用int或char一样使用PTRFUN了。
第二行的代码便使用这个新类型定义了变量pFun,此时就可以像使用形式1一样使用这个变量了。
一般情况下,这三个运算符没有重载的必要:
= 赋值运算符
& 取地址运算符
, 逗号运算符
- 重载运算符不能改变原先默认的运算符优先级,结合律和操作数数目
- 仅能重载现有运算符,不能创造新运算符
- 仅能重载应用于自定义数据类型操作数的运算符
我可以重载作用于HugeInt + HugeInt,HugeInt + int
的+
,但是不能重载作用于int + int
的+
定义方式
- 非静态的类成员函数
class Data{
public:
bool operator!() const;
};
- 全局函数
- friend:未访问私有数据成员或私有成员函数
- non-friend: 访问了私有数据成员或私有成员函数
class PhoneNumber{
friend ostream &operator<<(ostream&,const PhoneNumber&);
};
调用方式
普通函数
- 全局函数:
函数名(参数列表)
- 类成员函数:多数情况下,
对象.函数名(参数列表)
重载运算符
- 使用时以表达式形式出现,例:
HugeIntA+ HugeIntB
这里就不得不提示一下:
HugeIntA + intA
遇到这样的表达式,编译器会从两种重载函数调用形式中二选一(也就是程序员必须提供两者之一的重载运算符)
① HugeIntA.operator+(int);
class HugeInt{
public:
HugeInt operator+(int);
};
②operator+(HugeIntA,intA);
class HugeInt{
friend HugeInt operator+(const HugeInt&,int);
};
intB+ HugeIntB
遇到这样的表达式,编译器只承认一种重载函数调用形式
① int.operator+(HugeInt B);
非法,编译失败CE
②operator+(intB,HugeIntB);
class HugeInt{
friend HugeInt operator+(int,const HugeInt&);
};
设计原则
(),[],->
和赋值运算符=,+=,-=
必须重载为成员函数>>,<<
和需要支持交换律的运算符最好重载为全局函数- 其余运算符可以重载为成员函数,也可以重载为全局函数
- 当重载为类的成员函数时
- 自动包含该类对象(或其引用)作为操作数,因此函数参数个数等于运算符目数-1
- 左操作数(或唯一的操作数必须是该类对象(或对象引用)
- 当重载为全局函数时
- 函数参数个数等于运算符目数
对 输入流>>运算符 和 输出流<<运算符 的重载
//PhoneNumber.h
#ifndef PHONENUMBER_H
#define PHONENUMBER_H
#include<string>
#include<iostream>
using namespace std;
class PhoneNumber{
friend ostream &operator<<(ostream &,const PhoneNumber &);
//返回的是一个ostream类型的引用(cout的引用)
friend istream &operator>>(istream &,PhoneNumber &);
//返回的是一个istream类型的引用(cin的引用)
private:
string areaCode; //3-digit area code
string exchange; //3-digit exchange
string line; //4-digit line
};
#endif
//PhoneNumber.cpp
#include<iomanip>
#include<iostream>
#include"PhoneNumber.h"
using namespace std;
ostream &operator<<(ostream &output,const PhoneNumber &number) {
output<<"("<<number.areaCode<<")"<<number.exchange<<"-"<<number.line;
return output;
//Important! Enable cout<<a<<b<<c;
}
istream &operator>>(istream &input,PhoneNumber &number) {
input.ignore(); //skip (
input>>setw(3)>>number.areaCode;
input.ignore(2); //skip )and space
input>>setw(3)>>number.exchange;
input>>ignore(); //skip -
input>>setw(4)>>number.line;
return input;
//Important! Enable cin>>a>>b>>c;
}
#include<iostream>
using namespace std;
int main()
{
PhoneNumber phone;
cout<<"Enter phone number in the form (123) 456-7890: "<<endl;
cin>>phone;
cout<<"The phone number entered was: ";
cout<<phone<<endl;
return 0;
}