运算符重载(输入输出流运算符重载实例)

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章