运算符重载 |
1.用成员函数重载运算符 |
class x{ //... 返回类型 operator 运算符(形参表); }; 返回类型 X:operator 运算符(形参表) { 函数体; } |
例如(重载+使复数相加) |
#include <iostream> using namespace std; class Complex//复数类 { public: //定义默认构造函数初始化数据成员 Complex() { real = 0; imag = 0; } //定义初始化表初始化Complex类 Complex(double r, double i):real(r),imag(i){} //声明成员函数,实现复数相加 Complex complex_add(Complex &c1); void display( );//显示复数 private: double real;//复数的实部 double imag;//复数的虚部 }; //实现复数相加 Complex Complex::complex_add(Complex &c1) // 第一个complex是指返回类型。 { Complex c2; c2.real = c1.real + real; c2.imag = c1.imag + imag; return c2; } void Complex::display( )//显示复数 { cout<<real<<'+'<<imag<<'i'<<endl; } int main( ) { Complex c1(8,2), c2(7,10), c3; cout<<"c1 = "; c1.display(); cout<<"c2 = "; c2.display(); //执行两个复数相加 c3 = c1.complex_add(c2); cout<<"c1 + c2 = "; c3.display(); } |
2.上面的operator+还可以改写的更简练一些。 Complex Complex::operator+(Complex &c2) { return Complex(real+c2.real,image+c2.image);} |
3.注意重载运算符后,不改变其原来的功能。不改变运算符的优先级别。 |
4.对运算符重载的函数有两种处理方式(1)把运算符重载的函数作为类的成员函数;(2)运算符重载的函数不是类的成员函数,在类中把它声明为友元函数。 |
#include <iostream>
using namespace std;
class Complex//复数类
{
public:
Complex()
{
real = 0;
imag = 0;
}
Complex(double r, double i):real(r),imag(i){}
friend complex operator +(Complex &c1,Complex &c2); //在类中声明友元函数。
void display( );
private:
double real;
double imag;
};
Complex operator +(Complex &c1,Complex &c2);
{
return Complex(c1.real+c2.real,c1.image+c2.image);
}
void Complex::display( )
{
cout<<real<<'+'<<imag<<'i'<<endl;
}
int main( )
{
Complex c1(8,2), c2(7,10), c3;
cout<<"c1 = ";
c1.display();
cout<<"c2 = ";
c2.display();
c3 = c1.complex_add(c2);
cout<<"c1 + c2 = ";
c3.display();
注意和不是友元函数的区别。
|
5.重载双目运算符<,在STL中经常用到。 |
class Time { int month,day,hour,minute; public: Time(int mo,int d,int h,int mi) { month = mo,day = d,hour = h,minute = mi; } Time() { month = 1,day = 1,hour = 0,minute = 0; } friend bool operator<(Time t1,Time t2) { if(t1.getMonth()==t2.getMonth()) { if(t1.getDay()<=t2.getDay()) return 1; } else if(t1.getMonth()<=t2.getMonth()) { return 1; } return 0; }这是对时间的比较。 |
6.重载单目运算符 例如: |
#include<iostream> using namespace std; class Time {public: Time(){minute=0;sec=0;} Time(int m,int s):minute(m),sec(s){} Time operator++(); // 声明前置自增运算符“++”重载函数 Time operator++(int); //声明后置自增运算符“++”重载函数 void display(){cout<<minute<<":"<<sec<<endl;} private: int minute; int sec; }; Time Time::operator++() //定义前置自增运算符“++”重载函数 { if (++sec>=60) { sec-=60; ++minute; } return *this; //返回自加后的当前对象 } Time Time::operator++(int) { Time temp(*this); sec++; if (sec >= 60) { sec-=60; ++minute; } return temp; // 返回自增前的对象 } int main() { Time time1(34,59),time2; ++time1; time1.display(); time2 = time1 ++; time2.display(); return 0; |
7.重载输入输出运算符 |
friend istream&operator>>(istream&is,Time&);//先在类中声明 istream&operator>>(istream&is,Time&date) { is>>date.month>>date.day>>date.hour>>date.minute; return is; } friend ostream&operator<<(ostream&out,Time&);//需要先在类中声明 ostream&operator<<(ostream&out,Time&date) { out<<date.month<<" "<<date.day<<" "<<date.hour<<" "<<date.minute<<" "; return out; } |
STL |
1.vector vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。为了可以使用vector,必须在你的头文件中包含下面的代码:#include <vector>构造函数。 用法 vector<T>c 产生空的vector. vector<T>c1(c2) 产生同类型的才,并复制c2的所有元素。 vector<T>c(n)生成容器为n的vector。 vector<T>c(beg,end)产生一个vector以区间[beg,end]为元素初值、 ~vector<T>()销毁所有元素,并释放内存。 |
c.size()返回元素个数。 c.empty() 判断元素是否为空。 c.max_size() 返回元素最大可能数量。 c.capacity()返回重新分配空间前可容纳的最大元素数量。 c.reserve(n) 扩大容量n。 c1==c2 判断C1是否等于c2. c1=c2 将c2的全部元素赋值给c1. c.assign(beg,end) 将区间[beg,end]的元素赋值给c。 c1.swap(c2)将c1和c2 元素互换。 swap(c1,c2) 同上。 at(idx) 返回索引idx所标识的元素的引用。进行越界检查 operator[](idx) 返回索引idx所标识的元素的引用。不进行越界检查 front() 返回第一个元素的引用,不检查元素是否存在。 back()返回最后一个元素的引用,不检查元素是否存在。 rbegin() 返回一个逆向迭代器,指向逆向遍历的第一个元素。 rend() 返回一个逆向迭代器,指向逆向遍历的最后一个元素。 |
c.insert(pos,e) 在pos位置插入元素e的副本,并返回新元素的位置。 c.insert(pos,n,e) 在pos位置n个元素e的副本。 c.insert(pos,ben,end)在pos位置插入区间[beg,end)内所有元素的副本。 c.push_back() 在尾部添加一个元素e的副本。 |
c.pop_back() 移除最后一个元素但不返回最后一个元素。 c.erase(pos) 删除pos元素的位置,返回下一个元素的位置。 c.clear()移除所有元素,清空容器。 c.resize(num) 将元素数量改为num(增加函数用defalut构造函数的产生,多余元素被删除。 c.resize(num,e) 将元素数量改为num(增加元素是e的副本) |
#include <iostream> int main(){ cout << "Size: " << a.size() << endl; sort(a.begin(), a.end()); //升序排列 a.clear(); |
2. map/multimap |
count(key) 返回键值等于key的元素个数。 find(key) 返回键值等于key的第一个元素。 lower_bound(key) 返回键值大于key的第一个元素 upper_bound(key)返回键值大于key的第一个元素。 equal_range(key) 返回键值等于key的元素区间。 |
下面用一个代码介绍multimap #include <iostream> int main(){ cout << "COUNT: " << mm1.count("b") << endl; return 0; |
3.count_if 算法计算中的元素范围 [first, last) 导致返回 true,谓词的数量,并返回的谓词是真正的元素数。比count更灵活。 |
同理find_if 也一样。 |
下面给大家一个自己用STL写的程序 |
#include<iostream> #include<string> #include<map> #include<vector> #include<fstream> #include<algorithm> using namespace std; class Time { int month,day,hour,minute; public: Time(int mo,int d,int h,int mi) { month = mo,day = d,hour = h,minute = mi; } Time() { month = 1,day = 1,hour = 0,minute = 0; } friend bool operator<(Time t1,Time t2) { if(t1.getMonth()==t2.getMonth()) { if(t1.getDay()<=t2.getDay()) return 1; } else if(t1.getMonth()<=t2.getMonth()) { return 1; } return 0; } friend istream&operator>>(istream&is,Time&); friend ostream&operator<<(ostream&out,Time&); int getMonth() { return month; } int getDay() { return day; } int getHour() { return hour; } int getMinute() { return minute; } void setMonth(int d){month=d;} void setDay(int h){day=h;} void setHour(int g){hour=g;} void setMinute(int j){minute=j;} }; istream&operator>>(istream&is,Time&date) { is>>date.month>>date.day>>date.hour>>date.minute; return is; } ostream&operator<<(ostream&out,Time&date) { out<<date.month<<" "<<date.day<<" "<<date.hour<<" "<<date.minute<<" "; return out; } class Book // 用于添加图书馆的书 { Time chuban; string shuming; string shuhao; string zuozhe; int ceshu; public: Book(string ming,string shuh,string zuozh,Time chuba,int cesh):chuban(chuba) { shuming=ming; zuozhe=zuozh; shuhao=shuh; ceshu=cesh; } Book() { zuozhe="0000"; shuhao="0000"; Time chu(0,0,0,0); chuban=chu; ceshu=0; } friend istream&operator>>(istream&is,Book&); friend ostream&operator<<(ostream&out,Book&); string getShuming(){return shuming;} string getZuozhe(){return zuozhe;} string getShuhao(){return shuhao;} Time getChuban(){return chuban;} int getCeshu(){return ceshu;} }; istream&operator>>(istream&is,Book&R) { is>>R.shuming; if(R.shuming=="end")return is; is>>R.shuhao>>R.zuozhe>>R.chuban>>R.ceshu; return is; } ostream&operator<<(ostream&out,Book&R) { out<<R.shuming<<R.shuhao<<" "<<R.zuozhe<<" "<<R.chuban<<R.ceshu<<endl; return out; } class Record //借书记录 { string zhuanye; int banji; string shuming; string zuozhe; string shuhao; string xuehao; Time start,end,chuban; public: Record(string xh,string zhuany,int banj,string shu,string shumin,string zuozh,Time chuba,Time st,Time jie):chuban(chuba),start(st),end(jie) { zhuanye=zhuany; banji=banj; shuming=shumin; zuozhe=zuozh; xuehao=xh; shuhao=shu; } Record() { xuehao="000"; } friend istream&operator>>(istream&is,Record&); friend ostream&operator<<(ostream&out,Record&); string getShuming(){return shuming;} string getZuozhe(){return zuozhe;} string getShuhao(){return shuhao;} string getXuehao(){return xuehao;} Time getChuban(){return chuban;} Time getStart(){return start;} Time getEnd(){return end;} }; istream&operator>>(istream&is,Record&R) { is>>R.xuehao; if(R.xuehao=="end")return is; is>>R.xuehao>>R.shuhao>>R.zuozhe>>R.chuban>>R.start>>R.end; return is; } ostream&operator<<(ostream&out,Record&R) { out<<R.xuehao<<" "<<R.shuhao<<" "<<R.zuozhe<<" "<<R.chuban<<R.start<<R.end<<endl; return out; } struct cmp1 { string tpe; cmp1(string s) { tpe=s; } bool operator()(Record &a) { return (a.getShuming().find(tpe)!=string::npos); } }; class UserOp { public: vector<Book> b; vector<Book>::iterator it; multimap<string,int>b1;//书名 multimap<string,int>::iterator mit; vector<Record> r; vector<Record>::iterator itt; multimap<string,int >m1;//书名 multimap<string,int>::iterator mit1; multimap<string,int> m2;//书号 multimap<string,int>::iterator mit2; string manager; public: UserOp(string manage):manager(manage) { } UserOp() { manager="0000"; } friend istream&operator>>(istream&is,UserOp&u) { is>>u.manager; } friend ostream&operator<<(ostream&out,UserOp&u) { if(u.r.size()==0) {out<<u.manager<<" ";} if(u.r.size()!=0) { out<<u.manager<<endl; for(u.itt=u.r.begin();u.itt!=u.r.end();u.itt++) { out<<*(u.itt); } for(u.it=u.b.begin();u.it!=u.b.end();u.it++) { out<<*(u.it); } } return out; } int serchbook(string s); void addbook(); void addrecord(); void serchbyshuming(string s); void serchbyshuhao(string s); void shangjia(Book h); void xiajia(string s); }; void UserOp::addbook() { Book s; int i; while(1) { cin>>s; if(s.getShuming()=="end")break; b.push_back(s); i=b.size(); b1.insert(make_pair(s.getShuming(),i-1)); } } void UserOp::addrecord() { Record p; int i; while(1) { cin>>p; if(p.getXuehao()=="end")break; r.push_back(p); for(it=b.begin();it!=b.end();it++) { if((*it).getShuming()==p.getShuming()) { (*it).getCeshu()==(*it).getCeshu()-1; } } i=r.size(); m1.insert(make_pair(p.getShuming(),i-1)); m2.insert(make_pair(p.getShuhao(),i-1)); } } void UserOp::shangjia(Book h) { int i; b.push_back(h); i=b.size(); b1.insert(make_pair(h.getShuming(),i-1)); } int UserOp::serchbook(string s) { mit=b1.find(s); if(mit!=b1.end()) { return mit->second; } } void UserOp::xiajia(string s) { int i; i=serchbook(s); it=b.begin()+i; b.erase(it); b1.erase(b1.find(s)); } void UserOp::serchbyshuming(string s) { itt=find_if(r.begin(),r.end(),cmp1(s)); while(itt!=r.end()) { // it=v.begin()+mit1->second; cout<<*itt; itt=find_if(itt+1,r.end(),cmp1(s)); } } int main() { /*vector<Book> b; vector<Book>::iterator it; multimap<string,int>b1;//书名 multimap<string,int>::iterator mit; vector<Record> r; vector<Record>::iterator itt; multimap<string,int >m1;//书名 multimap<string,int>::iterator mit1; multimap<string,int> m2;//书号 multimap<string,int>::iterator mit2;*/ UserOp u; cin>>u; u.addbook(); u.addrecord(); cout<<u; } |
最后给大家分享一下心得。 首先,运算符重载是很重要的,很有实用意义,丰富了类的功能和适用范围,重载时一般都是基于原来的功能进行延伸不能太违背原来的意思,比如 |
把加号重载成小于号用。重载一次一劳永逸,为下面节省很多,而且使程序更清晰。STL 使是以模板为基础的一个标准库,使c++的重要的一部分。 它非常有实用性,运用STL能使代码更简洁。我们要对STL各种容器及其特有的一些功能都要了解,用的时候也便于查找。 |
重载运算符与STL总结