一.运算符重载
运算符重载使得用户自定义的数据以一种更简洁的方式工作
具体格式
class X {
//…
返回类型 operator运算符(形参表);
//…
}
在类外定义成员运算符函数的格式如下:
返回类型 X::operator运算符(形参表)
{
函数体
}
1.重载运算符的限制:
不能重载的运算符:
.成员访问运算符
.*成员指针访问运算符
::域运算符
?:条件运算符
Sizeof长度运算符
= () [] ->
可以重载的运算符:+ - * / % ^ & | ~
! = < > += -= *= /= %
^= &= |= << >> >>= <<= == !=
<= >= && || ++ -- ->* ‘ ->
[] () new delete new[] delete[]
重载运算符函数可以对运算符做出新的解释,但原有基本语义不变:
(1),不改变运算符的优先级
(2),不改变运算符的结合性
(3),不改变运算符所需要的操作数
(4),不能创建新的运算符
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 )
左右操作数都由参数传递
3.运算符重载函数不能有默认的参数
4.只能以成员函数形重载的运算符:
[ ]下标运算符
=赋值运算符
()函数调用运算符
->用指针访问对象成员
5.只能重载为非成员函数的运算符:
流插入运算符<<流提取运算符>>
6.重载运算符[ ]和()
(1)重载下标运算符 []
[] 运算符用于访问数据对象的元素
重载格式: 类型 类 ::operator[] ( 类型) ;
例
设 x 是类 X 的一个对象,则表达式
x[ y ]
可被解释为
x. operator [ ] ( y )
(2)重载函数调用符 ()
() 运算符用于函数调用
重载格式: 类型 类 ::operator() ( 参数表 );
例
设 x 是类 X 的一个对象,则表达式
x( arg1, arg2, … )
可被解释为
x. operator () (arg1, arg2, … )
7.<</>>流插入\输出运算符重载
重载输出运算符“<<”(只能被重载成友元函数,不能重载成成员函数)
定义输出运算符“<<”重载函数的一般格式如下:
ostream& operator<<(ostream& out,class_name&obj)
{
out<<obj.item1;
out<<obj.item2;
.. .
out<<obj.itemn;
return out;
}
重载输入运算符“>>” (只能被重载成友元函数)
定义输入运算符函数“>>”重载函数的一般格式如下:
istream& operator>>(istream& in,class_name&obj)
{
in>>obj.item1;
in>>obj.item2;
. . .
in>>obj.itemn;
return in;
}
8.++/--重载
设 A Aobject ;
运算符 ++和 - - 有两种方式:
前置方式: ++Aobject --Aobject
成员函数 重载 A :: A operator++ () ;
解释为: Aobject . operator ++( ) ;
友元函数 重载 friend A operator++ (A &) ;
解释为: operator ++( Aobject ) ;
后置方式: Aobject ++ Aobject --
成员函数 重载 A :: A operator++ (int) ;
解释为: Aobject . operator ++(0 ) ;
友元函数 重载: friend A operator++ (A &, int) ;
解释为: operator++(Aobject, 0);
重载输出输入流
istream&operator>>(istream&in,class_name&obj)
{
in>>obj.item1;
in>>obj.item2;
. . .
in>>obj.itemn;
return in;
}
只能被重载成友元函数,不能重载成成员函数
总结:
运算符重载是给以运算符新的定义功能,来更方便的进行计算实现功能。
重载运算符总体可以分为两类:成员函数重载,友元函数重载
本章总的学习是一元二元运算符重载 关系运算符重载 输出输入运算符重载 ++和--运算符重载 赋值运算符重载
二.STL
1.简介
(1)STL是C++标准程序库的核心,深刻影响了标准程序库的整体结构。
(2)STL由一些可适应不同需求的集合类(collection class),以及在这些数据集合上操作的算法(algorithm)构成
(3)STL内的所有组件都由模板(template)构成,其元素可以是任意类型。
(4)STL是所有C++编译器和所有操作系统平台都支持的一种库。
STL是由容器、迭代器、容器适配器、算法四部分组成。
2.STL容器类别
(1)序列式容器——排列次序取决于时机和位置
(2)关联式容器——排列顺序取决于特定准则
STL容器的共同能力
所有容器中存放的都是值而非引用。如果希望存放的不是副本,容器元素只能是指针。
所有元素都形成一个次序(order),可以按相同的次序一次或多次遍历每个元素。
STL容器元素的条件
必须能够通过拷贝构造函数进行复制
必须可以通过赋值运算符完成赋值操作
必须可以通过析构函数完成销毁动作
序列式容器元素的默认构造函数必须可用
某些动作必须定义operator =,例如搜寻操作
关联式容器必须定义出排序准则,默认情况是重载operator <(对于基本数据类型(int,long,char,double,……)而言,以上条件总是满足)
3.容器的共同操作
初始化(initialization)
产生一个空容器
std::list<int>l;
以另一个容器元素为初值完成初始化
std::list<int>l;
…
std::vector<float> c(l.begin(),l.end());
以数组元素为初值完成初始化
intarray[]={2,4,6,1345};
…
std::set<int>c(array,array+sizeof(array)/sizeof(array[0]));
与大小相关的操作(size operator)
size()-返回当前容器的元素数量
empty()-判断容器是否为空
max_size()-返回容器能容纳的最大元素数量
比较(comparison)
==,!=,<,<=,>,>=
比较操作两端的容器必须属于同一类型
如果两个容器内的所有元素按序相等,那么这两个容器相等
采用字典式顺序判断某个容器是否小于另一个容器
赋值(assignment)和交换(swap)
swap用于提高赋值操作效率
迭代器(iterator)
可遍历STL容器内全部或部分元素的对象
指出容器中的一个特定位置
所有容器都提供两种迭代器
container::iterator以“读/写”模式遍历元素
container::const_iterator以“只读”模式遍历元素
begin()-返回一个迭代器,指向第一个元素
end()-返回一个迭代器,指向最后一个元素之后
rbegin()-返回一个逆向迭代器,指向逆向遍历的第一个元素
rend()-返回一个逆向迭代器,指向逆向遍历的最后一个元素之后
赋值(assignment)和交换(swap)
swap用于提高赋值操作效率
capacity返回vector能容纳的元素最大数量。如果插入元素时,元素个数超过capacity,需要重新配置内部存储器
- vec.begin()//指向迭代器中第一个元素。
- vec.end()//指向迭代器中末端元素的下一个,指向一个不存在元素。
- vec.push_back(elem) //在尾部加入一个数据。
- vec.pop_back() //删除最后一个数据。
- vec.capacity() //vector可用空间的大小。
- vec.size()//返回容器中数据个数。
- vec.empty() //判断容器是否为空。
- vec.front() //传回第一个数据。
- vec.back() //传回最后一个数据,不检查这个数据是否存在。
- vec.at(index) //传回索引idx所指的数据,如果idx越界,抛出out_of_range。
- vec.clear() //移除容器中所有数据。
- vec.erase(iterator) //删除pos位置的数据,传回下一个数据的位置。
- vec.erase(begin,end) //删除[beg,end)区间的数据,传回下一个数据的位置。注意:begin和end为iterator
- vec.insert(position,elem) //在pos位置插入一个elem拷贝,传回新数据位置。
- vec.insert(position,n,elem) //在pos位置插入n个elem数据,无返回值。
- vec.insert(position,begin,end) //在pos位置插入在[beg,end)区间的数据,无返回值。
(1)头文件#include<vector>.
(2)创建vector对象,vector<int> vec;
(3)尾部插入数字:vec.push_back(a);
(4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的。
(5)使用迭代器访问元素.
vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++)
cout<<*it<<endl;
(6)插入元素: vec.insert(vec.begin()+i,a);在第i+1个元素前面插入a;
(7)删除元素: vec.erase(vec.begin()+2);删除第3个元素
vec.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始
(8)向量大小:vec.size();
(9)清空:vec.clear();
vector创建容器- #include<iostream>
- #include<vector>
- #include<list>
- #include<deque>
- using namespace std;
- int main()
- {
- vector<int>obv;
- cout<<"obv的元素个数为:"<<obv.size()<<endl;
- double sz[5]={1,2,3,4,5};
- deque<double>obD(sz,sz+5);
- for(unsigned int i=0;i<obD.size();i++)
- {
- cout<<obD[i]<<" ";
- }
- cout<<endl;
- list<float>obL(3,5);
- list<float>::iterator iter=obL.begin();
- while(iter!=obL.end())
- {
- cout<<(*iter)<<" ";
- iter++;
- }
- cout<<endl;
- return 0;
- }
map/multimap
使用平衡二叉树管理元素
元素包含两部分(key,value),key和value可以是任意类型必须包含的头文件#include <map>
根据元素的key自动对元素排序,因此根据元素的key进行定位很快,但根据元素的value定位很慢
不能直接改变元素的key,可以通过operator []直接存取元素值
map中不允许key相同的元素,multimap允许key相同的元素
(3)set/multiset
使用平衡二叉树管理元素
集合(Set)是一种包含已排序对象的关联容器。
必须包含的头文件#include <set>
map容器是键-值对的集合,好比以人名为键的地址和电话号码。相反地,set容器只是单纯的键的集合。当我们想知道某位用户是否存在时,使用set容器是最合适的。
set中不允许key相同的元素,multiset允许key相同的元素。
三.学习总结