运算符重载及STL总结

重载运算符的限制 :不能重载的算符  

. :: .* ?: sizeof

可以重载的运算符 
+ - * / % ^ & | ~
! = < > += -= *= /= %
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- ->* ->

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

重载运算符函数可以对运算符作出新的解释,但原有基本语义不变:
1.不改变运算符的优先级
2.不改变运算符的结合性
3.不改变运算符所需要的操作数 

4.不能创建新的运算符

运算符函数可以重载为成员函数或友元函数:一元运算符 Object  op    或    op  Object

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

Object . operator op ()
操作数由对象Object通过this指针隐含传递
重载为友元函数,解释为:
operator op (Object)

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

二元运算符:ObjectL  op ObjectR

重载为成员函数,解释为:
ObjectL . operator op ( ObjectR )
    左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递 
重载为友元函数,解释为:
operator op ( ObjectL, ObjectR )

  左右操作数都由参数传递 

双目运算符重载为成员函数:对双目运算符而言,成员运算符函数的形参表中仅有一个参数,它作为运算符的右操作数,此时当前对象作为运算符的左操作数,它是通过this指针隐含地传递给函数的。 
         :有一个Time类,包含数据成员minute(分)和sec(秒),模拟秒表,每次走一秒,满60秒进一分钟,此时秒又从0开始算。要求输出分和秒的值。
class Time
{
public:
Time( ){minute=0;sec=0;}
Time(int m,int s):minute(m),sec(s){ }
Time operator++( );     //声明前置自增运算符“++”重载函数
Time operator++(int);   //声明后置自增运算符“++”重载函数
private:
int minute;
int sec;

};

ime Time∷operator++( )    //定义前置自增运算符“++”重载函数
{
if(++sec>=60) {
sec-=60;         //满60秒进1分钟
++minute;
}
return *this;          //返回当前对象值
}
Time Time∷operator++(int)  //定义后置自增运算符“++”重载函数
{
Time temp(*this);
sec++;
if(sec>=60) {
sec-=60;
++minute;
}
return temp;         //返回的是自加前的对象

}

用友元函数重载:在第一个参数需要隐式转换的情形下,使用友元函数重载
    运算符是正确的选择
 友元函数没有 this 指针,所需操作数都必须在参数表显式
    声明,很容易实现类型的隐式转换
 C++中不能用友元函数重载的运算符有

=    ()    []    ->

成员运算符函数与友元运算符函数的比较 :(1) 成员运算符函数比友元运算符函数少带一个参数(后置的++、--需要增加一个形参)。
  (2)  双目运算符一般可以被重载为友元运算符函数或成员运算符函数,但当操作数类型不相同时,必须使用友元函数。 
  重载赋值运算符:赋值运算符重载用于对象数据的复制 
 operator= 必须重载为成员函数 
重载函数原型为:

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

重载运算符[]和():1.重载下标运算符 [] :[] 运算符用于访问数据对象的元素 重载格式类型  类 :: operator[]  ( 类型 ) ;

例 :设 x 是类 X 的一个对象,则表达式
x [ y ]
可被解释为

x . operator [ ] ( y )

2.重载函数调用符 () :() 运算符用于函数调用重载格式 类型  类 :: operator()  ( 参数表  ) ;

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

x ( arg1, arg2, … )
可被解释为

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

重载流插入和流提取运算符 :istream 和 ostream 是 C++ 的预定义流类
cin 是 istream 的对象,cout 是 ostream 的对象
运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据

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

STL:STL是C++标准程序库的核心,深刻影响了标准程序库的整体结构
STL由一些可适应不同需求的集合类(collection class),以及在这些数据集合上操作的算法(algorithm)构成
STL内的所有组件都由模板(template)构成,其元素可以是任意类型

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

STL组件
容器(Container) - 管理某类对象的集合
迭代器(Iterator) - 在对象集合上进行遍历
算法(Algorithm) - 处理集合内的元素
容器适配器(container adaptor)

函数对象(functor) 

STL容器元素的条件
必须能够通过拷贝构造函数进行复制
必须可以通过赋值运算符完成赋值操作
必须可以通过析构函数完称销毁动作
序列式容器元素的默认构造函数必须可用
某些动作必须定义operator ==,例如搜寻操作

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

vector
非变动操作:

c.size()

返回元素个数

c.empty()

判断容器是否为空

c.max_size()

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

c.capacity()

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

c.reserve(n)

扩大容量为n

c1==c2

判断c1是否等于c2

c1!=c2

判断c1是否不等于c2

c1<c2

判断c1是否小于c2

c1>c2

判断c1是否大于c2

c1<=c2

判断c1是否大于等于c2

c1>=c2

判断c1是否小于等于c2

c1 = c2

c2的全部元素赋值给c1

c.assign(n,e)

将元素en个拷贝赋值给c

c.assign(beg,end)

将区间[beg,end]的元素赋值给c

c1.swap(c2)

c1c2元素互换

swap(c1,c2)

同上,全局函数

at(idx)

返回索引idx所标识的元素的引用,进行越界检查

operator [](idx)

返回索引idx所标识的元素的引用,不进行越界检查

front()

返回第一个元素的引用,不检查元素是否存在

back()

返回最后一个元素的引用,不检查元素是否存在

begin()

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

end()

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

rbegin()

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

rend()

返回一个逆向迭代器,指向逆向遍历的最后一个元素

c.insert(pos,e)

pos位置插入元素e的副本,并返回新元素位置

c.insert(pos,n,e)

pos位置插入n个元素e的副本

c.insert(pos,beg,end)

pos位置插入区间[beg,end]内所有元素的副本

c.push_back(e)

在尾部添加一个元素e的副本

c.pop_back()

移除最后一个元素但不返回最后一个元素

c.erase(pos)

删除pos位置的元素,返回下一个元素的位置

c.erase(beg,end)

删除区间[beg,end]内所有元素,返回下一个元素的位置

c.clear()

移除所有元素,清空容器

c.resize(num)

将元素数量改为num(增加的元素用defalut构造函数产生,多余的元素被删除)

c.resize(num,e)

将元素数量改为num(增加的元素是e的副本)

map/multimap
使用平衡二叉树管理元素
元素包含两部分(key,value),key和value可以是任意类型
必须包含的头文件#include <map>
根据元素的key自动对元素排序,因此根据元素的key进行定位很快,但根据元素的value定位很慢
不能直接改变元素的key,可以通过operator []直接存取元素值

map中不允许key相同的元素,multimap允许key相同的元素

set/multiset
使用平衡二叉树管理元素
集合(Set)是一种包含已排序对象的关联容器。
必须包含的头文件#include <set>
map容器是键-值对的集合,好比以人名为键的地址和电话号码。相反地,set容器只是单纯的键的集合。当我们想知道某位用户是否存在时,使用set容器是最合适的。

set中不允许key相同的元素,multiset允许key相同的元素

:vector向量操作

判断向量大小:v.size()
清空向量操作:v.clear()
判断向量空则返回1    v.empty()
程序如下:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
vector<int> v;
for(int i=0;i<10;i++)
{
v.push_back(i); 
}
for(vector<int>::iterator it=v.begin();it!=v.end();it++)
{
cout<<*it<<" ";
}
cout<<endl;
//输出向量大小
cout<<"清空前向量中元素个数"<<v.size()<<endl;
//判断是否为空,如果空则返回1
cout<<"是否为空"<<v.empty()<<endl;
//清空向量 
v.clear();
cout<<"清空后向量中元素个数"<<v.size()<<endl;
cout<<"是否为空"<<v.empty()<<endl;
system("pause");
return 0;    
} 
对于以上知识的学习心得:运算符重载是 为了实现类的多态性(多态是指一个函数名有多种含义) 运算符的操作需要修改类对象的状态,则使用成员函数。如需要做左值操作数的运算符(如=,+=,++) 运算时,有数和对象的混合运算时,必须使用友元 二元运算符中,第一个操作数为非对象时,必须使用友元函数。当参数不会被改变,一般按const引用来传递(若是使用成员函数重载,函数也为const).但这些在编写时易犯错,或是不清楚需不需要重载,还需要在更多的练习中体会。STL听老师说在编写时很方便,但是我并不能很好掌握,甚至说不怎么会用容器,在类中更改容器时常出错,不知道怎么运用各种表达式以及函数调用,也不怎么清楚函数的功能,使用起来到变得更加麻烦,有点强行使用的感觉。类与对象学习的有点朦朦胧胧,加上STL就更加混乱,时常对于一个知识有点概念了下一个知识马上就来了,显得力不从心,对于这两章还需多多练习,多加理解。


猜你喜欢

转载自blog.csdn.net/Fred_TT/article/details/80415490
今日推荐