c++学习(二 )——重载操作符

原创 2007年10月07日 08:43:00
输入输出操作符
支持I/O操作的类所提供的I/O操作接口,一般应该与标准库iostream为内置类型定义的接口相同。因此,许多类都需要重载输入和输出操作符。
输出操作符<<的重载
为了与IO标准库一致,操作符应接受ostream&作为第一个形参,对类类型const对象的引用作为第二个形参,并返回对ostream形参的引用。
重载输出操作符一般的简单定义如下:
// general skeleton of the overloaded ouput operator
Ostream& operator <<(ostream& os, const ClassType &object)
{
 // any special logic to prepare object
 
 // actual ouput of members
 os << //…
 // return ostream object
 return os;
}
第一个形参是对ostream对象的引用,在该对象上产生输出,ostream为非const,因为下入到流会改变流的状态。该形参是一个引用,因为不能复制ostream对象。
第二个对象一般应是对要输出的类类型的引用。该形参是一个引用以避免复制实参。它可以是const,因为输出一个对象不应该改变该对象。
返回类型是一个ostream引用,它的值通常是输出操作符所操作的ostream对象。
输出操作符通常所做格式化应尽量少。
关于输出,累设计者面临着一个重要决定:是否格式化以及进行多少格式化。
一般而言,输出操作符应输出对象的内容,进行最小限度的格式化,他们不应该输出换行符。
用于内置类型的输出操作符所作的格式化很少,并且不输出换行符。通过限制输出操作符只输出对象的内容,如果需要执行任意额外的格式化,我们让用户决定该如何处理。尤其是,输出操作符不应该输出换行符。尽量减少操作符所作的格式化,让用户自己控制输出细节。
IO操作符必须为非成员函数
当定义符合标准库iostream规范的输入或输出操作符的时候,必须使它成为非成员操作符。
我们不能将该操作符定义为类的成员,否则,左操作数将只能是该类类型的对象。
// if operator << is a member of Sales_item
Sales_item item;
item << cout;
这个用法与为其他类型定义的输出操作符的正常使用方式相反。如果想要支持正常的用法,则左操作数必须为ostream类型。如果该操作符是类的成员,则它必须是ostream类的成员,然而ostream类是标准库的组成部分,我们是不能为标准库的类增加成员的。
如果想要使用重载操作符为该类型提供IO操作,就必须将他们定义为非成员函数。IO操作符通常对非公用数据成员进行读写,因此,类通常将IO操作符设为友元。
 
输入操作符>>的重载
与输出操作符类似:输入操作符的第一个形参是一个引用,指向它要读的流,并且返回的也是对同一个流的引用。它的第二个形参是对要读入的对象的非const引用,该形参必须为非const,因为输入操作符的目的是将数据读到这个对象中。
ostream& operator >>(ostream& os, ClassType &object)
需要注意的是:输入和输出操作符有如下区别,输入操作符必须处理错误和文件结束的可能性。
如何处理输入错误
如果输入操作符检测到输入失败了,则确保对象处于可用和一致的状态是个好做法。如果对象在错误发生之前已经写入了部分欣喜,这样做就特别重要。
如果发生了错误,就将形参恢复为空对象,以避免给它一个无效的状态。用户如果需要知道输入是否成功,可以测试流。即使用户忽略了输入可能错误,对象仍处于可用状态——他的成员已经定义。
设计输入操作符时,如果可能,要确定错误恢复措施,这很重要。
指出错误
除了处理可能发生的任何错误之外,输入操作符还可能需要设置输入形参的条件状态。我们的输入操作符相当简单——我们只关心读入期间可能发生的错误。
 
算术操作符和关系操作符
一般而言,将算术和关系操作符定义为非成员函数。为了与内置操作符保持一致,加法返回一个右值,而不是一个引用
例:
// assumes that both objects refer to the same isbn
Sales_item operator +(const Sales_item& lhs, const Sales_item& rhs)
{
   Sales_item ret(lhs);
   ret += rhs;
   return ret; // ret 因该理解为左值还是右值呢?概念有所混淆 我觉得返回的是左值
}
算术操作符通常产生一个新值,该值是两个操作数的计算结果,它不同于任一操作数且在一个局部变量中计算,返回对那个变量的引用是一个运行时的错误。
既定义了算术操作符又定义了相关复合赋值操作符的类,一般应使用复合赋值实现算术操作符。
 
赋值操作符
类赋值操作符接受类类型的形参,通常,该形参是对类类型的const引用,但也可以是类类型或对类类型的非const 引用。如果没有定义这个操作符,编译器就会合成它。类赋值操作符必须是类的成员,以便编译器可以知道是否需要合成一个。
赋值操作符可以重载。无论形参为何种类型,赋值操作符必须定义为成员函数。
赋值必须返回对*this的引用。
因为赋值返回的是一个引用,就不需要创建和撤销结果的临时副本。返回值通常是左操作数的引用。
注意:一般而言,赋值操作符与复合赋值操作符应返回左操作数的引用。
 
下标操作符
下标操作符必须定义为类成员函数。
提供读写访问
定义下标操作符比较复杂的地方在于,它在用作赋值的左右操作数时都应该能表现正常,下标操作符出现在左边,必须生成左值,可以指定引用作为返回类型而得到左值。只要下标操作符返回引用,就可用作赋值的任意一方。
类定义下标操作符的时候,一般需要定义两个版本:一个为非const成员并返回引用,另一个为const成员并返回const引用。
 
自增操作符和自减操作符
定义自增/自减操作符
C++语言不要求自增操作符或自减操作符一定作为类的成员,但是,因为这些操作符改变操作对象的状态。但是,因为这些操作符改变操作对象的状态,所以更倾向于将他们作为成员函数。
定义前自减/前自增操作符
class CheckedPtr
{
 public:
      CheckedPtr& operator++();
      CheckedPtr& operator—();
};
为了与内置类型一致,前缀式操作符应返回被增量或减量对象的引用。
区别操作符的前缀和后缀形式
前缀式和后缀式存在一个问题:它们的形参数目和类型相同
为了解决这个问题,后缀式操作符函数接受一个额外的int型形参。使用后缀式操作符时,编译器提供0座位这个形参的实参。
定义后缀式操作符
class CheckedPtr
{
 public:
     CheckedPtr operator ++ (int);
     CheckedPtr operator – (int);
};
为了与内置操作符一致,后缀式操作符应返回旧值(尚未自增或自减的值),并且应作为值返回,而不是返回应用。
一般而言,最好前缀式和后缀式都定义。只定义前缀式或只定义后缀式的类,将会让习惯于使用两种形式的用户感到奇怪。
 
调用操作符和函数对象
可以为类类型的对象重载函数调用操作符。一般为表示操作的类重载调用操作符。
例如,可以定义名为absInt的结构,该结构将int类型的值转换为绝对值得操作:
class absInt
{
   int operator()(int val)
{
 Return val < 0 ? –val: val;
}
};
这个结构很简单,它定义了一个操作,函数调用操作符,该操作符有一个形参并返回形参的绝对值。
通过类类型的对象提供一个实参表而使用调用操作符,所用的方式看起来像一个函数调用。
函数调用操作符必须声明为成员函数,一个类可以定义函数调用操作符的多个版本,由形参的数目或类型加以区别。
定义了调用操作符的类,其对象常称为函数对象,即它们是行为类似函数的对象。
 
 
 
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

C++学习笔记39——重载输入输出操作符

1,重载运算符综述 (1)不能定义自己的新运算符,只能对已存在的运算符重载; (2)C++中大部分运算符都能重载,但仍有5个例外:            . (成员访问运算符)    .*(成...

C++学习笔记42——重载操作符之箭头操作符

箭头(->)操作符,看起来很像二元操作符,左操作数是类对象,右操作数是类成员,即使如此,箭头操作符的重载函数是没有第二个形参的(第一个是隐含形参this),理解起来有点难度;  函数语句为:  a->...

C++学习笔记40——重载作符之算术操作符与关系操作符

1,概述 (1)如前一节所述,一般应将算术操作符和关系操作符定义为类的友元函数; (2)编译器不会默认合成算术操作符和关系操作符,所以你如果不定义这些操作符,就没有办法在类对象上使用它们,这一点与赋值...

C++学习笔记41——重载操作符之下标操作符

1,概述 (1)下标操作符operator[]必须定义为类的成员函数; (2)下标操作符用在赋值操作符左右两边时,均应表现正常。故其应返回引用。 (3)一般应该定义const与非const两个版...

C++学习笔记(七)--操作符重载 友元函数 类的继承 访问控释protected

C++ Primer Plus学习(七),分为下面几个部分: 操作符重载 友元函数 类的继承 访问控制protected //这个系列暂定的最后一篇

C++学习之四、重载C++操作符

-----本文是基于大家已经知道重载C++操作符的基础上强化一些知识    为什么要重载操作符 1. 让类表现得像内置数据类型一样 2. 能够对程序中的表现有更多的控制     操作符重...

C++学习笔记9-操作符重载

1. 重载操作符必须具有一个类类型操作数 用于内置类型的操作符,其含义不能改变。例如,内置的整型加号操作符不能重定义: // error: cannotredefine built-in operat...
  • wzhiu
  • wzhiu
  • 2014-07-18 09:16
  • 812

c++学习笔记(9.操作符重载)

本节知识点:

C++学习之友元函数,操作符重载

这是我写的第一个类,分数类型,虽然比较简单,但我犯的错也并不少,比方成员函数和全局函数打代码时总是搞混,输入负的分数时也出现各种变态的输出,还发现了一个以前不知道的知识点就是 a*1.0/b 和a/b...

C++学习-------类继承之友元和操作符重载

/********************************************************************************* 这一次的代码没有什么东西,只是用...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)