重载 STL

第7章  运算符重载

7.1.1 重载运算符的限制

不能重载的算符         

.      ::     .*     ?:     sizeof

可以重载的运算符

+    -     *     /      %     ^    &    |      ~

!      =    <    >    +=  -=   *=   /=   %

^=  &= |=   <<  >>  >>=      <<=      ==  !=

<=  >=  && ||     ++  --   ->* ‘      ->

[]     ()     new delete   new[]     delete[]

重载运算符函数可以对运算符作出新的解释,但原有基本语义不变:

Ø  不改变运算符的优先级

Ø  不改变运算符的结合性

Ø  不改变运算符所需要的操作数

Ø  不能创建新的运算符

Ø  运算符函数可以重载为成员函数或友元函数 

7.2 用成员或友元函数重载运算符

1.一元运算符

Object op    或    op  Object

Ø  重载为成员函数,解释为:

       Object. operator op ()

       操作数由对象Object通过this指针隐含传递

Ø  重载为友元函数,解释为:

       operatorop (Object)

操作数由参数表的参数Object提供

2.二元运算符

ObjectL  op ObjectR

Ø  重载为成员函数,解释为:

       ObjectL . operator op ( ObjectR )

    左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递

Ø  重载为友元函数,解释为:

       operator op ( ObjectL, ObjectR )

     左右操作数都由参数传递

       成员运算符函数的原型在类的内部声明格式如下:

class X {

    //…

返回类型 operator运算符(形参表);

  //…

}

在类外定义成员运算符函数的格式如下:

返回类型 X::operator运算符(形参表)

{

     函数体

}

7.2.2  用友元函数重载

class   Complex

{     int   Real ;     int    Imag ;

   public:

       Complex ( int a ) { Real = a ;   Imag = 0 ; }    

       Complex ( int  a  ,int  b ) { Real = a ;   Imag = b ; }

       Complex operator + ( Complex ) ;

       …...

} ;  

int   f ( )

{Complex  z ( 2 , 3 ) ,   k ( 3 , 4 ) ;

   z = z + 27 ;           

   z = 27 + z ;           

      …...

}

Ø  在第一个参数需要隐式转换的情形下,使用友元函数重载

    运算符是正确的选择

Ø   友元函数没有 this 指针,所需操作数都必须在参数表显式

    声明,很容易实现类型的隐式转换

Ø   C++中不能用友元函数重载的运算符有

       =   ()    []    ->

成员运算符函数与友元运算符函数的比较 

  (1) 成员运算符函数比友元运算符函数少带一个参数(后置的++、--需要增加一个形参)。

  (2)  双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数。

 

7.3  几个典型运算符重载

设   A Aobject ;

运算符 ++和 - - 有两种方式:

前置方式:   ++Aobject   --Aobject

  成员函数  重载       A :: A operator++ () ;

       解释为:       Aobject . operator ++( ) ;

    友元函数  重载   friend A operator++ (A &) ;

       解释为:      operator ++( Aobject ) ;          

  成员函数  重载       A :: A operator++ (int) ;

       解释为:      Aobject . operator ++( 0 ) ;

    友元函数  重载:       friend A operator++ (A &, int) ;    

       解释为:      operator++(Aobject, 0)

7.3.2 重载赋值运算符

Ø  赋值运算符重载用于对象数据的复制

Ø   operator= 必须重载为成员函数

Ø  重载函数原型为:

       类名  &  类名  :: operator= ( 类名 ) ;

7.3.3  重载运算符[]和()

Ø  运算符[] 和 () 是二元运算符

Ø   [] 和 ()只能用成员函数重载,不能用友元函数重载

1.重载下标运算符 []

[] 运算符用于访问数据对象的元素

重载格式       类型  类 ::operator[]  ( 类型 ) ;

       设 x 是类 X 的一个对象,则表达式

              x [ y ]

       可被解释为

              x . operator [ ] ( y )

2.重载函数调用符 ()

() 运算符用于函数调用

重载格式       类型  类 ::operator()  ( 参数表  ) ;

       设 x 是类 X 的一个对象,则表达式

              x ( arg1, arg2, … )

       可被解释为

              x . operator () (arg1, arg2, … )

7.3.4  重载流插入和流提取运算符

Ø  istream 和 ostream 是 C++的预定义流类

Ø  cin 是 istream 的对象,cout是 ostream 的对象

Ø  运算符<< 由ostream 重载为插入操作,用于输出基本类型数据

Ø  运算符>> 由 istream 重载为提取操作,用于输入基本类型数据

Ø  用友元函数重载<< 和 >> ,输出和输入用户自定义的数据类型

重载输出运算符“<<”(只能被重载成友元函数,不能重载成成员函数)

      定义输出运算符“<<”重载函数的一般格式如下:

    ostream&operator<<(ostream& out,class_name& obj)

    {

         out<

         out<

          .. .

         out<

          return out;

    }

重载输入运算符“>>” (只能被重载成友元函数)

         定义输入运算符函数 “>>”重载函数的一般格式如下:

    istream&operator>>(istream& in,class_name& obj)

    {

            in>>obj.item1;

           in>>obj.item2;

            . . .

           in>>obj.itemn;

            return in;

    }

例题

1.

定义point类,重载>>,<<运算符,实现point对象的输入、输出

定义复数Complex类,重载>>,<<运算符,实现Complex对象的输入、输出

#include

class Point{

  int x,y;

public:

  friend istream & operator >>(istream & in, Point&p);

  friend ostream & operator<<(ostream & out, Point&p);

};

istream & operator>>(istream & in, Point &p){

  cout<<"Please input a point:"<

  in>>p.x; in>>p.y; return in;}

ostream &operator<<(ostream & out, Point &p){

  out<<"("<

int main(){

  Point p;

  cin>>p;

  cout<

  return 0;

}

2.

 设计一个集合类,用无符号整数数组表示集合,重载运算符实现集合的基本运算,以及集合元素的输入、输出。

//setTypeHead.h

#include

using namespace std;

//集合类

class setType

{  public:

         setType( unsigned e=128 );           //构造函数

         setType( const setType & B ); //复制构造函数

         ~setType();                      //析构函数

         setType operator+= ( unsigned x );     //重载+=,把元素x并入集合

         setType operator= ( setType B );   //重载=,集合变量赋值

         setType operator() (unsigned x=0);     //重载(),集合置元素x,默认置空

         setType operator+ ( setType B );   //重载+,求并集

         setType operator* ( setType B );    //重载*,求交集

         setType operator- ( setType B );    //重载-,求差集

         bool operator<= ( setType B );      //重载<=,判集合蕴含


STL:

C++ 标准模板库
C++ Standard Template Libarary

STL概述

STL是C++标准程序库的核心,深刻影响了标准程序库的整体结构

STL由一些可适应不同需求的集合类(collectionclass),以及在这些数据集合上操作的算法(algorithm)构成

STL内的所有组件都由模板(template)构成,其元素可以是任意类型

STL是所有C++编译器和所有操作系统平台都支持的一种库

STL组件

容阿器(Container)- 管理某类对象的集合

迭代器(Iterator) -在对象集合上进行遍历

算法(Algorithm) -处理集合内的元素

容器适配器(containeradaptor

函数对象(functor)

STL容器的共同能力

所有容器中存放的都是值而非引用。如果希望存放的不是副本,容器元素只能是指针。

所有元素都形成一个次序(order),可以按相同的次序一次或多次遍历每个元素

STL容器元素的条件

必须能够通过拷贝构造函数进行复制

必须可以通过赋值运算符完成赋值操作

必须可以通过析构函数完称销毁动作

序列式容器元素的默认构造函数必须可用

某些动作必须定义operator ==,例如搜寻操作

关联式容器必须定义出排序准则,默认情况是重载operator <

 

STL容器的共同操作

Ø  与大小相关的操作(sizeoperator

size()-返回当前容器的元素数量

empty()-判断容器是否为空

max_size()-返回容器能容纳的最大元素数量

Ø  比较(comparison

==,!=,<,<=,>,>=

比较操作两端的容器必须属于同一类型

如果两个容器内的所有元素按序相等,那么这两个容器相等

采用字典式顺序判断某个容器是否小于另一个容器

Ø  赋值(assignment)和交换(swap)

swap用于提高赋值操作效率

Ø  与迭代器(iterator)相关的操作

begin()-返回一个迭代器,指向第一个元素

end()-返回一个迭代器,指向最后一个元素之后

rbegin()-返回一个逆向迭代器,指向逆向遍历的第一个元素

rend()-返回一个逆向迭代器,指向逆向遍历的最后一个元素之后

迭代器(iterator

Ø  迭代器分类

双向迭代器

可以双向行进,以递增运算前进或以递减运算后退、可以用==和!=比较。

list、set和map提供双向迭代器

随机存取迭代器

除了具备双向迭代器的所有属性,还具备随机访问能力。

可以对迭代器增加或减少一个偏移量、处理迭代器之间的距离或者使用<和>之类的关系运算符比较两个迭代器。

vector、deque和string提供随机存取迭代器

vector

Ø  vector模拟动态数组

Ø  vector的元素可以是任意类型T,但必须具备赋值和拷贝能力(具有public拷贝构造函数和重载的赋值操作符)

Ø  必须包含的头文件#include

Ø  vector支持随机存取

Ø  vector的大小(size)和容量(capacity)

size返回实际元素个数,

capacity返回vector能容纳的元素最大数量。如果插入元素时,元素个数超过capacity,需要重新配置内部存储器。

操作

效果

vector c

产生空的vector

vector c1(c2)

产生同类型的c1,并将复制c2的所有元素

vector c(n)

利用类型T的默认构造函数和拷贝构造函数生成一个大小为n的vector

vector c(n,e)

产生一个大小为n的vector,每个元素都是e

vector c(beg,end)

产生一个vector,以区间[beg,end]为元素初值

~vector()

销毁所有元素并释放内存。

操作

效果

c.size()

返回元素个数

c.empty()

判断容器是否为空

c.max_size()

返回元素最大可能数量(固定值)

c.capacity()

返回重新分配空间前可容纳的最大元素数量

c.reserve(n)

扩大容量为n

c1==c2

判断c1是否等于c2

c1!=c2

判断c1是否不等于c2

c1

判断c1是否小于c2

c1>c2

判断c1是否大于c2

c1<=c2

判断c1是否大于等于c2

c1>=c2

判断c1是否小于等于c2

map/multimap

Ø  构造、拷贝和析构

操作

效果

map c

产生空的map

map c1(c2)

产生同类型的c1,并复制c2的所有元素

map c(op)

以op为排序准则产生一个空的map

map c(beg,end)

以区间[beg,end]内的元素产生一个map

map c(beg,end,op)

以op为排序准则,以区间[beg,end]内的元素产生一个map

~ map()

销毁所有元素并释放内存。

Ø  非变动性操作

操作

效果

c.size()

返回元素个数

c.empty()

判断容器是否为空

c.max_size()

返回元素最大可能数量

c1==c2

判断c1是否等于c2

c1!=c2

判断c1是否不等于c2

c1

判断c1是否小于c2

c1>c2

判断c1是否大于c2

c1<=c2

判断c1是否大于等于c2

c1>=c2

判断c1是否小于等于c2

Ø  赋值

操作

效果

c1 = c2

将c2的全部元素赋值给c1

c1.swap(c2)

将c1和c2的元素互换

swap(c1,c2)

同上,全局函数

Ø  特殊搜寻操作

操作

效果

count(key)

返回”键值等于key”的元素个数

find(key)

返回”键值等于key”的第一个元素,找不到返回end

lower_bound(key)

返回”键值大于等于key”的第一个元素

upper_bound(key)

返回”键值大于key”的第一个元素

equal_range(key)

返回”键值等于key”的元素区间

map/multimap

Ø  安插(insert)元素

操作

效果

c.erase(pos)

删除迭代器pos所指位置的元素,无返回值

c.erase(val)

移除所有值为val的元素,返回移除元素个数

c.erase(beg,end)

删除区间[beg,end]内所有元素,无返回值

c.clear()

移除所有元素,清空容器

STL容器

操作

效果

begin()

返回指向第一个元素的迭代器

clear()

清除所有元素

count()

返回某个值元素的个数

empty()

如果集合为空,返回true

end()

返回指向最后一个元素的迭代器

equal_range()

返回集合中与给定值相等的上下限的两个迭代器

erase()

删除集合中的元素

find()

返回一个指向被查找到元素的迭代器

get_allocator()

返回集合的分配器

 

例题:

pair模板:  

pair模板可以用于生成key-value

#include

#include

using namespace std;

main()  {

  typedefset<double,less>double_set;

  constint SIZE = 5;

  doublea[SIZE] = {2.1,4.2,9.5,2.1,3.7 };

  double_setdoubleSet(a,a+SIZE);

  ostream_iterator output(cout,"");

  cout<< "1) ";

  copy(doubleSet.begin(),doubleSet.end(),output);

  cout<< endl;

  pair<double_set::const_iterator, bool> p;

  p= doubleSet.insert(9.5);

  if(p.second)

  cout<< "2) " << * (p.first) << " inserted" << endl;

  else

  cout<< "2) " << * (p.first) << " not inserted" << endl;

}

//insert函数返回值是一个pair对象, first是被插入

输出:

1)2.1 3.7 4.2 9.5

2)9.5 not inserted




心得

重载运算符在我看来主要是用来使对象之间可以做运算操作的.

定义了一个类的对象a而这个对象中有一个数据,又定义了一个b对象也有一个数据,你须要使用a+b来计算这两个对象中数据的合,就须要运算符重载.
运算符重载不光是可以重载四则运算的.也可以重载 []下标运算符,<< >>输入输出运算符等等.
运算符重载主要的用途只是为了让运算符其前后跟后的对象可以直接像对象内的数据一样运算
但也仅限于了解,但具体如何用,还是有些找不到头绪

对于STL的应用,虽然是个方便的方法,不过一直处于似懂非懂的状态,不知道该如何用它代替平时学的方式,自我感觉很有难度。。。

你可能感兴趣的:(重载 STL)