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++ 重载操作符 operator

参数个数的限定     非成员函数:   单目运算符:参数表中只有一个参数;   双目运算符:参数表中只有两个参数       成员函数:   单目运算符:参数表中没有参数; ...
  • fenhong91
  • fenhong91
  • 2017年02月07日 09:55
  • 1031

C++ STL 基础及应用(2) 模板与操作符重载

模板是 C++ 语言中重要的概念。它提供了一种通用的方法来开发重用的代码,即以创建参数化的 C++ 类型。 本章将阐述一些具体的 STL 模板思想,并简单介绍操作符重载与模板的联系。 文中将给出一个简...
  • Raito__
  • Raito__
  • 2016年05月22日 17:13
  • 2675

C++重载[]数组操作符

#include #include using namespace std; class CharPair{ public: CharPair(){ } CharPair(char f...
  • w397090770
  • w397090770
  • 2012年03月18日 14:46
  • 6364

对于c++中流操作符重载的理解

对于IO成员函数的重载不应该是一个成员函数的方式,并且应该声明为友元 一、如果为成员函数,都会有一个某人的参数,也就是this指针,为左操作数,下面考虑将其声明为成员函数的方式 对于cout 对于...
  • lightblueme
  • lightblueme
  • 2015年03月28日 13:01
  • 753

C++面向对象操作符重载:调用操作符和函数对象

1、定义了调用操作符的类,其对象常称为函数对象,即它们是行为类似函数的对象。      可以为类类型的对象重载函数调用操作符。一般为表示操作的类重载调用操作符。函数调用操作符必须声明为成员函数。一个...
  • QQrenzai
  • QQrenzai
  • 2015年11月11日 08:58
  • 1099

所有C++操作符重载的例子

1.[ ]操作符重载 C++语言规定:“[ ]”只能作为类的成员函数进行重载。 “[ ]”是C++中的下标运算符,对于数组或指针来说,下表运算的语义是确定的,不能进行重载。因此,如果看到一个运算...
  • chijianxingfeng
  • chijianxingfeng
  • 2013年04月30日 13:04
  • 2450

C++运算符重载(12) - 重载数组索引操作符[]

本篇主要讨论索引操作符[]的重载。 下面是关于重载[]的一些注意事项: 1) 当需要检测下标是否越界时,重载[]是很有用的。 2) 重载函数必须返回引用,因为类似的表达式“arr[i]”可以被当成一个...
  • shltsh
  • shltsh
  • 2015年05月27日 00:15
  • 1412

C++运算符重载(4) - 不能被重载的操作符

C++,中,下面的操作符是不能被重载的: . (成员访问或点操作符) ?: (三元操作符或条件操作符) :: (范围操作符) .* (指向成员的指针操作符) sizeof (取对象大小操作符) typ...
  • shltsh
  • shltsh
  • 2015年05月26日 09:39
  • 2173

C++类—重载操作符

重载操作符是具有特殊名称的函数:保留字operator后接定义的操作符符号。如: [cpp] view plaincopy Sales_item o...
  • xietingcandice
  • xietingcandice
  • 2014年09月29日 16:13
  • 858

C++ 重载操作符之一(指针运算符*,->)

//重载指针运算符*,-> #include using namespace std; template class MyPtr { private: T * m_ptr; public: ...
  • u014338577
  • u014338577
  • 2015年09月06日 23:24
  • 2352
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:c++学习(二 )——重载操作符
举报原因:
原因补充:

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