C++运算符重载
“<<”和“>>”本来是在C++中被定义为左/右位移运算符的,由于在iostream头文件中对它们进行了重载,所以使用它们能用作标准数据类型数据的输入和输出运算符。因此,在使用它们的程序中必须包含:#include <iostream>
1. 运算符重载例子:
例1重载函数作为Complex类的成员函数
分析:C++编译系统将程序中的表达式c1 + c2解释为:
c1.operator +(c2)
即以c2为实参调用对象c1的运算符重载函数operator +(Complex &c2)。实际上,运算符重载函数有两个参数,由于重载函数是Coplex类中的成员函数,有一个参数是隐含的,运算符函数是用this指针隐式地访问类对象的成员,如this->real+c2.real,this代表c1,即实际上是c1.real+c2.real。
运算符重载函数可以是类的成员函数,也可以是类的友元函数,也可以是普通函数(不推荐)。
例2 重载函数作为Complex类的友元函数
为什么把运算符函数作为友元函数呢?理由很简单,因为运算符函数要访问Complex类对象中的成员。如果作为成员函数,就必须要求运算表达式第一个参数(即运算符左侧的操作数)是一个类对象,而且与运算符函数的类型相同,在例1中,表达式c1+c2中的第一个参数c1是Complex类对象,运算符函数返回值的类型也是Complex,这是正确的。如果c1不是Complex类,就无法启用c1.operator +(c2),也就无法通过隐式this指针访问Complex类的成员了。
说明:有的C++编译系统(如VC++6.0)没有完全实现C++标准,它所提供的后缀.h的头文件不支持把成员函数重载为友元函数,因此在VC++6.0,应把程序的头两行:
#include <iosteam>
using namespace std;
改为一行:#include <iosteam.h> //C语言的风格
例3 重载双目运算符
例4 重载单目运算符
说明:重载后置自增运算符时,多了一个int型的参数,增加这个参数只是为了与前置自增运算符重载函数有所区别,此外没有任何作用。
例5 重载流插入/提取运算符
对“<<”和“>>”重载的函数形式如下:
istream & operator >>(istream &, 自定义类 &); //input
ostream & operator >>(ostream &, 自定义类 &); //output
例如:
编译系统把”cout<<c3”解释为:operator <<(cout, c3),即以cout和c3作为实参,调用operator <<(ostream &output, Complex &c)函数。因此,相当于执行了:
cout<<”(”<<c3.real<<”+”<<c3.image<<”i)”<<endl; return cout;
返回的是流提取对象cout,作为引用返回。
如果有以下输出:
cout<<c3<<c2;
先处理cout<<c3,即(cout<<c3)<<c2;而cout<<c3其实是operator <<(cout, c3),返回的是流提取对象cout,所以cout再和后面的c2结合,输出c2的内容。可见为什么C++规定“流提取运算符重载函数的第一个参数和函数的类型都必须是ostream类型的引用”了,就是为了返回cout,以便连续输出。
问:为什么要在operator前面加’&’?(即“返回引用”)
答:开始我以为ostream & operator >>()的这个返回类型“ostream &”是为了和括号中的参数“ostream &”类型相对于,其实不然。因为只有运算符重载函数为成员函数时,才要求第一个参数和运算符重载函数的类型相同,而友元函数没有这个要求。
先分析“ostream &”作为参数的情况,传入的第一个参数显然是cout,cout是什么,它其实也是一个类的对象,“cin和cout分别是istream类和ostream类的对象”,所以说形参定义成引用,避免了对象的拷贝。
再来分析函数类型为什么要定义为“ostream &”,先看看原理http://blog.csdn.net/zollty/article/details/6695311。因为要使返回的对象cout能够直接使用,所以要将函数的返回值定义为引用。
2. 不同数据类型之间的转换
a. 标准类型数据之间的转换
显示类型转换:
C语言格式:(类型名)数据,例如:(int)89.5
C++格式:类型名(数据),例如:int(89.5)
b. 用构造函数进行类型转换
几种构造函数:
l 默认构造函数(无参,直接指定默认值):Complex();
l 用于初始化的构造函数:Complex(double r, double i);
l 用于复制对象的复制构造函数:Complex(Complex &c);
l 现在要讲解的新构造函数——转换构造函数:Complex(double r){ real=r; imag=0; }(它只有一个参数)
以上几种构造函数可以同时出现在同一个类中,它们是构造函数的重载。
假如有以下声明语句:
Complex c1(3.5); //建立对象c1,由于只有一个参数,调用转换构造函数
也可以用声明语句建立一个无名的Complex类对象。如:
Complex(3.6); //用声明语句建立一个无名对象,合法,但是无法使用
可以在一个表达式中使用无名对象,如
c1=Complex(3.6); //假设c1已经被定义为Complex类对象
若在程序中有以下表达式:
c=c1+2.5;
编译出错,因为不能用运算符“+”将一个Complex类对象和一个浮点数相加。可以先将2.5转换成Complex类无名对象,然后相加:
c=c1+Complex(2.5);
请对比Complex(2.5)和int(2.5)。可以认为Complex(2.5)的作用也是强制类型转换。通常把有一个参数的构造函数用作类型转换,所以,称为转换构造函数。如可以将一个学生类对象转换为教师类对象,可以在Teacher类中写出下面的转换构造函数:
Teacher(Student &s)
{ num=s.num; strcpy(name, s.name); sex=s.sex; }
但应注意:对象s中的num, name, sex必须是公用成员,否则不能被类外调用。
c. 用类型转换函数进行类型转换
用转换构造函数可以将一个指定类型的数据转换为类的对象。但是不能反过来将一个类的对象转换为一个其他类型的数据(例如将一个Complex类对象转换成double类型数据)。C++提供了类型转换函数来解决这个问题。类型转换函数的作用是将一个类的对象转换成另一类型的数据。如果已经声明了一个Complex类:
可以在Complex类中这样定义类型转换函数:
operator double()
{ return real; }
它的作用是将一个Complex类对象转换为一个double型数据,其值是Complex类中得数据成员real的值。请注意:函数名是operator double。这点是和运算符重载时的规律一致的(都是用关键字operator开头,只是被重载的是类型名)。其特点:在函数名前面不能指定函数类型,函数也没有参数。其返回值的类型是由函数名中指定的类型名来确定的(函数返回double型变量real的值)。
在定义了前面的数据类型转换函数后,程序中的Complex类对象是不是一律都转换成double类型的数据呢?不是的,它们具有双重身份,既是Complex类对象,又可以作为double类型数据。
转换构造函数和类型转换运算符有一个共同的功能:当需要的时候,编译系统会自动的调用这些函数,建立一个无名的临时对象(或临时变量)。例如,若已定义d1, d2为double型变量,c1, c2为Complex类对象,且类中已经定义了类型转换函数。设程序中有以下表达式:
d1 = d2 + c1;
编译系统发现“+”左侧的d2是double型,而右侧的c1是Complex类对象,如果没有对运算符“+”进行重载,就会检查有无类型转换函数,结果发现有,就调用operate double函数把Complex类对象c1转换为double型数据,建立了一个临时的double变量,并与d2相加,最后将一个double的值赋给d1。相当于执行表达式:
d1 = d2 + c1.operate double();
如果类中已经定义了转换构造函数并重载了运算符“+”(作为Complex类的友元函数),但未对double定义类型转换函数(或者说未对double重载),若有以下表达式:
c2 = c1 + d2;
则系统将转换为:
c2 = c1+ Complex(d2);
当然,如果既有转换构造函数和运算符重载,又有double类型转换函数,出现歧义的话就会出错。
分享到:
相关推荐
在给定的实例中,你将学习如何实际应用这些概念,通过成员函数和非成员函数重载C++运算符,以及如何使用友元函数来实现特定的运算行为。通过练习和理解这些例子,你将更好地掌握C++中运算符重载和友元函数的使用。
详细介绍 C++运算符重载 的PPT 文中部分内容: 下标运算符“[ ]”重载 C++把下标运算符[ ]看成一个双目运算符,其操作数为<基本表达式>和<表达式>,对应的运算符为operator[ ],必须重载为一个成员函数。对于下标...
C++允许重载的运算符和不允许...C++运算符重载的规则 C++对运算符重载定义了如下几条规则。 1) C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。 例如,有人觉得BASIC中用“**“作为幂运算符很方便
在C++编程语言中,运算符重载是一个关键特性,它允许我们为已存在的运算符赋予新的含义,以便在自定义类型上使用...通过对C++运算符重载的深入理解和实践,你可以编写出更加自然、直观的代码,提升代码质量和可维护性。
中国农业大学C++课程课件,信息与电气工程学院学生专用。
"Visual C++ 运算符重载详细总结" Visual C++ 运算符重载是指在 C++ 编程语言中对已有的运算符进行重新定义,以适应自定义的数据类型和操作。这种技术可以使得程序员能够使用熟悉的运算符来操作自定义的数据类型,...
C++运算符重载 C++运算符重载是面向对象程序设计中的一种重要概念,它允许开发者重新定义运算符的行为,以符合特定类的需求。运算符重载是通过在类中定义特殊的成员函数或友元函数来实现的,这些函数的名称以...
"c++运算符重载矩阵运算" c++运算符重载矩阵运算是指在c++语言中对矩阵进行运算的操作,包括加、减、乘、转置、赋值等操作。这些操作都是通过重载运算符来实现的。 首先,我们需要定义一个Matrix类,该类有三个...
C++运算符重载的课件 C++运算符重载是C++程序设计中一个非常重要的概念,它允许用户自定义的数据类型以一种更简洁的方式工作,使得代码更加简洁易读。运算符重载使得用户可以定义自己的运算符,以便更好地描述问题...
C++运算符重载函数作为类成员函数和友元函数 C++运算符重载函数是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。运算符重载实质上是函数的重载。重载运算符的...
C++运算符重载学习笔记 C++类和对象是面向对象编程的基础概念。运算符重载是C++中的一种重要机制,允许开发者重新定义已有的运算符,赋予其新的功能,以适应不同的数据类型。在本文中,我们将详细介绍C++运算符重载...
### C++运算符重载详解 #### 一、前言 C++允许用户自定义类或结构体,并为这些类型重载内置运算符,从而使得这些类型能够像内置类型一样使用标准运算符进行操作。本篇文章将通过三个具体的示例来深入探讨C++中的...
C++运算符重载是C++中一个强大的特性,它允许程序员为自定义类型定义运算符的行为。在C++中,运算符重载有三种主要形式:成员函数、友元函数以及普通函数。每种形式都有其特定的使用场景和优缺点。 1. 成员函数重载...
C++运算符重载 C++语言提供了运算符重载机制,允许程序员对已有的运算符赋予新的含义,使其应用于用户自定义的类。运算符重载是对已有的运算符赋予多重含义,同时保持其原有的优先级和结合性。 什么是运算符重载?...
C++ 运算符重载 本节主要介绍 C++ 运算符重载的概念、语法和应用。运算符重载是 C++ 的一个重要特性,允许开发者重新定义运算符的行为,以适应不同的需求。 首先,运算符重载的语法形式如下:返回类型 operator@...
### C++运算符重载教学和编程中易被忽视的问题 #### 1. 二元运算符重载为类成员函数时易忽视的问题及解决方法 以复数类为例,在实现复数相加的过程中,很容易忽略一个重要的设计原则:**当一个二元运算符(如加法...
首先,我们要理解C++中的运算符重载。运算符重载允许我们在不同的上下文中为同一个运算符赋予不同的含义,这在处理自定义数据类型如矩阵时非常有用。例如,我们可以通过重载"+"运算符来实现矩阵的相加,重载"-...