《C和C++代码精粹》——1.12 运算符重载

1.12 运算符重载

C和C++代码精粹
在C++中你可以重载运算符,例如,定义一个复数的数据类型如下:

struct complex
{
    double real, imag;
};

假如能使用中缀符号用于复数加法,那将会相当方便。如:

complex c1,c2;
…
complex c3=c1+c2;

当编译器遇到如c1+c2这样的表达式时,将查找下边两个函数中的一个(只须其中的一个存在):

operator+(const complex&,const complex &);    //全局函数
complex::operator+(const complex &);           //成员函数

关键字operator是函数名的一部分。为实现两个复数的加法可以将operator+定义为全局类型,如下:

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

程序清单1.14 运算符+和运算符<<在复数中的应用

#include <iostream>
using namespace std;  

struct complex
{
    double real, imag;
    complex(double = 0.0, double = 0.0);
};  

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

inline ostream& operator<<(ostream &os, const complex &c)
{
    os << '(' << c.real << ',' << c.imag << ')';
    return os;
}  

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

不允许重载系统中预定义的操作,例如,不允许重载两个整型数相加。因此,在重载操作中至少有一个操作数是用户自定义类型。

流库“知道”怎样通过运算符重载来格式化各种系统预定义的数据类型。例如,ostream类中,cout是一个实例,它为所有的系统预定义的数据类型都重载了操作符<<,当编译器看到表达式:

cout<<i;
这里i是整型,它产生以下的函数运算:

cout.operator<<(i); //ostream::operator<<(ostream&,int)
这样可以正确地格式化数据。

程序清单1.14表明如何通过重载用于复数的运算符<<来扩展标准流(输出在程序清单1.5中)。编译器将表达式

cout<<c
转换成下面的函数调用(在这里c是一个复数):

operator << ( cout ,c)
这将依次采用operator<<(ostream&,const complex&)将操作分解成格式化系统预定义类型的对象。这个函数也返回流,因此,可以在一个单独的语句中链接多个插入流。如,表达式

cout<<c1<<c2
变为

operator<<(operator<<(cout,c1),c2)
这要求operator<<(ostream&, const complex&)返回流,为了高效这是通过引用来实现的。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

时间: 2024-09-18 12:37:11

《C和C++代码精粹》——1.12 运算符重载的相关文章

C++之运算符重载(1)

在前一节中曾提到过,C++中运行时的多态性主要是通过虚函数来实现的,而编译时的多态性是由函数重载和运算符重载来实现的.这一系列我将主要讲解C++中有关运算符重载方面的内容.在每一个系列讲解之前,都会有它的一些基础知识需要我们去理解.而运算符重载的基础就是运算符重载函数.所以今天主要讲的是运算符重载函数. 1.运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用域不同类型的数据导致不同行为的发生.比如 int i; int i1=10,i2=10; i=i1+i2; std::cout<<

《C和C++代码精粹》——2.12 指向函数的指针

2.12 指向函数的指针 C和C++代码精粹 一个指针可以指向函数也可以指向存储的对象.下面的语句声明fp是一个指向返回值为整型(int)的函数的指针: int(*fp)( ); *ftp的圆括号是必需的,没有它的语句 int *fp( ); 将fp声明为一个返回指向整型(int)指针的函数.这就是将星号与类型声明紧密相连的方式成为逐渐受人们欢迎的方式的原因之一. int fp(); //方式说明fp()返回一个指向整型的指针(int ) 当然,这种方式建议你通常应该每条语句只声明一个实体,否则

《C和C++代码精粹》导读

前言 C和C++代码精粹 本书适合于那些C和C++的职业程序员.假如你已熟悉这两种语言的语法和基本结构,这本书能够为你创建有效的.实用的程序提供实践性的指导.每一个代码范例或程序范例均标明行之有效的用法和技术,这些用法和技术对C/C++这两种重要编程语言的性能发挥起着重要的作用. 对于那些希望在工作中加强自身技术和提高效率的人来说,本书可以算是一本经验之谈.尽管目前人们对面向对象模式的推崇到了白热状态(本书也包括这方面的丰富内容),可是我没有理由不对C++的基础-C表示尊崇.我发现太多的程序开发

《C和C++代码精粹》——2.7 指针和一维数组

2.7 指针和一维数组 C和C++代码精粹 在程序清单2.7中,会注意到在传递数组 s 时并没有使用它的地址,这是因为C和C++在大多数表达式中把数组名转换成指向它第一个元素的指针.自1984年以来,我已经向成百上千的学生讲授了C和C++,我注意到了指针和数组,特别是指针和多维数组之间的关系造成很多迷惑. 这样说似乎很奇怪,但是C++确实不支持数组,至少C++不像支持第一类数据类型如整型或者甚至结构体那样支持数组.考虑以下的语句: int i=1,j; int a[4]={0,1,2,3},b[

《C和C++代码精粹》——1.10 操纵器

1.10 操纵器 C和C++代码精粹 当标识符 endl出现在一个输出流中时,一个换行字符就被插入并且流被刷新.标识符endl是操纵器的一个例子,即为了副效应而插入到流的一个对象.在〈iostream〉中被声明的系统预定义的操纵器列于表 1.3中.程序清单1.11里的程序在功能上与程序清单1.10的程序等价,但它是用操纵器来代替显式调用setf函数.操纵器经常可以使代码更为高效. 表1.3 简单的操纵器(〈iostream〉) 程序清单1.11 用操纵器改变数据基数 // base2.cpp:

《C和C++代码精粹》——第 1 章 更好的C1.1 两种语言简述

第 1 章 更好的C C和C++代码精粹本文仅用于学习和交流目的,不代表异步社区观点.非商业转载请注明作译者.出处,并保留本文的原始链接. 1.1 两种语言简述 C和C++代码精粹20世纪80年代初期,C++起源于AT&T,称为带类的 C,当时Bjarne Stroustrup试图用Simula-67编写仿真程序."类"在Simula中是表示用户定义类型的术语,编写好的仿真程序的关键是能够定义对象反映现实世界.除了把类加到C中使其成为最快的过程语言外,还有什么更好的方法可以得到

《C和C++代码精粹》——2.8 数组作为参数

2.8 数组作为参数 C和C++代码精粹当你把数组作为参数传递给一个函数,正如所预期的那样,是传递了指向数组第一个元素的指针.因此,可以在调用的函数中永久地改变数组元素的值.在程序清单2.12的函数f中,地址&a[0]按值传递给指针b,因此表达式b[i]就和表达式a[i]完全是一样的了.不可能按值传一个完整的内置数组. 即使用数组符号定义了参数b,即: int b[] 它同下面这种写法是完全一样的. int *b 程序清单2.12 说明作为参数的数组实际上是指针 // array5.cpp: 数

《C和C++代码精粹》——1.15 new和delete

1.15 new和delete C和C++代码精粹在C语言中为了用堆栈,需要计算出所要创建的对象的大小: struct Foo*fp =malloc(sizeof(struct Foo) ); 在C++中,运算符new用于计算出对象的大小: Foo*fp=new Foo; 在C语言中分配数组,需调用不同的函数. struct Foo*fpa= calloc(n,sizeof(struct Foo)); 在C++中,new运算符会知道数组的大小: Foo*fpa=new Foo[n]; 此外,运算

《C和C++代码精粹》——1.8 标准流

1.8 标准流 C和C++代码精粹C++中有4个预定义的流:cin(标准输入),cout(标准输出),cerr(标准错误),clog(标准错误).除了cerr外其余都是全缓冲流.就像stderr一样,cerr的行为好象是非缓冲的,但事实上它是单元缓冲的,也就是说它在处理完每一个对象而不是每一个字节后会自动清除缓冲.例如,带有单元缓冲的语句: cerr<<"hello":缓冲处理5个字符,然后清除缓冲区.一个非缓冲处理的流会立即发送每个字符到它的最终目的地. 程序清单1.5