类和对象(高级)
类和对象(高级)
一、运算符重载
运算符重载是对已有的运算符 指定新功能。不能创建新运算。
运算符重载关键字operator
思路:
1、弄懂运算符的运算对象的个数。(个数决定了 重载函数的参数个数)
2、识别运算符左边的运算对象 是类的对象还是其他.
类的对象:成员函数实现(推荐,少一个参数),全局函数实现(不推荐)
其他:只能是全局函数实现
1、重载<<运算符(全局函数实现)
#include <iostream>
#include<string>
using namespace std;
class Person{friend ostream& operator <<(ostream &out,Person &ob );
private:int num;string name;float score;
public:Person(){}Person(int num,string name,float score):num(num),name(name),score(score){}
};
//返回cout的引用类型(可以链式输出)
ostream& operator <<(ostream &out,Person &ob ){out<<ob.num<<" "<<ob.name<<" "<<ob.score;return out;
}
int main(int argc, char *argv[])
{Person lucy(100,"lucy",19.2f);Person bob(102,"bob",19.3f);cout<<lucy<<endl;//链式 输出cout<<lucy<<bob<<endl;return 0;
}
2、重载输入>>运算符
#include <iostream>
#include<string>
using namespace std;
class Person{friend ostream& operator<<(ostream &out,Person &ob );friend istream& operator>>(istream &in,Person &ob);
private:int num;string name;float score;
public:Person(){}Person(int num,string name,float score):num(num),name(name),score(score){}};
//返回cout的引用类型(可以链式输出)
ostream& operator<<(ostream &out,Person &ob ){out<<ob.num<<" "<<ob.name<<" "<<ob.score;return out;
}
istream &operator>>(istream &in,Person &ob){
in>>ob.num>>ob.name>>ob.score;
return in;
}
int main(int argc, char *argv[])
{Person lucy;cin>>lucy;cout<<lucy<<endl;return 0;
}
如果使用全局函数 重载运算符 必须将全局函数设置成友元。
3、可以重载的运算符

4、重载加法运算符+(全局函数实现)
#include <iostream>
#include<string>
using namespace std;
class Person{friend ostream& operator<<(ostream &out,Person ob );friend istream& operator>>(istream &in,Person &ob);friend Person operator +(Person ob1,Person ob2);
private:int num;string name;float score;
public:Person(){}Person(int num,string name,float score):num(num),name(name),score(score){}};
//返回cout的引用类型(可以链式输出)
ostream& operator<<(ostream &out,Person ob ){out<<ob.num<<" "<<ob.name<<" "<<ob.score;return out;
}
istream &operator>>(istream &in,Person &ob){
in>>ob.num>>ob.name>>ob.score;
return in;
}
//返回值不能为引用,因为temp是局部变量
Person operator +(Person ob1,Person ob2){Person temp;temp.num=ob1.num+ob2.num;temp.name=ob1.name+ob2.name;temp.score=ob1.score+ob2.score;return temp;}
int main(int argc, char *argv[])
{Person lucy(100,"lucy", 88.8f);Person bob(101,"bob", 99.9f);Person tom(102,"tom", 77.7f);cout<<lucy+bob+tom<<endl;return 0;
}
5、重载加法运算符+(成员函数实现 推荐)
#include <iostream>
#include<string>
using namespace std;
class Person{friend ostream& operator<<(ostream &out,Person ob );friend istream& operator>>(istream &in,Person &ob);
private:int num;string name;float score;
public:Person(){}Person(int num,string name,float score):num(num),name(name),score(score){}
//成员函数实现重载Person operator +(Person ob2){Person temp;temp.num=this->num+ob2.num;temp.name=this->name+ob2.name;temp.score=this->score+ob2.score;return temp;}};
//返回cout的引用类型(可以链式输出)
ostream& operator<<(ostream &out,Person ob ){out<<ob.num<<" "<<ob.name<<" "<<ob.score;return out;
}
istream &operator>>(istream &in,Person &ob){
in>>ob.num>>ob.name>>ob.score;
return in;
}int main(int argc, char *argv[])
{Person lucy(100,"lucy", 88.8f);Person bob(101,"bob", 99.9f);Person tom(102,"tom", 77.7f);cout<<lucy+bob+tom<<endl;return 0;
}
6、重载==运算符(成员函数实现 推荐)
#include <iostream>
#include<string>
using namespace std;
class Person{friend ostream& operator<<(ostream &out,Person ob );friend istream& operator>>(istream &in,Person &ob);
private:int num;string name;float score;
public:Person(){}Person(int num,string name,float score):num(num),name(name),score(score){}Person operator +(Person ob2){Person temp;temp.num=this->num+ob2.num;temp.name=this->name+ob2.name;temp.score=this->score+ob2.score;return temp;}//成员函数重载==运算符bool operator ==(Person &ob){if(num==ob.num&&name==ob.name&&score==ob.score){return true;}else{return false;}}};
//返回cout的引用类型(可以链式输出)
ostream& operator<<(ostream &out,Person ob ){out<<ob.num<<" "<<ob.name<<" "<<ob.score;return out;
}
istream &operator>>(istream &in,Person &ob){
in>>ob.num>>ob.name>>ob.score;
return in;
}int main(int argc, char *argv[])
{Person lucy(100,"lucy", 88.8f);
// Person bob(101,"bob", 99.9f);Person bob(100,"lucy", 88.8f);
if(lucy==bob){
cout<<"相等"<<endl;
}
else{cout<<"不相等"<<endl;
}return 0;
}
7、重载++运算符
++a(前置++),它就调用operator++(a),
a++(后置++),它就会去调用operator++(a,int)
案例1:重载后置++
类名称 operator++(int)
{old=//先保存旧的值
//自增++return old;//返回旧值}
#include <iostream>
#include<string>
using namespace std;
class Person{friend ostream& operator<<(ostream &out,Person ob );friend istream& operator>>(istream &in,Person &ob);
private:int num;string name;float score;
public:Person(){}Person(int num,string name,float score):num(num),name(name),score(score){}Person operator +(Person ob2){Person temp;temp.num=this->num+ob2.num;temp.name=this->name+ob2.name;temp.score=this->score+ob2.score;return temp;}bool operator ==(Person &ob){if(num==ob.num&&name==ob.name&&score==ob.score){return true;}else{return false;}}//后置++Person operator ++(int a){Person old;old.num=num;old.name=name;old.score=score;num+=1;name+=name;score+=score;return old;}};
//返回cout的引用类型(可以链式输出)
ostream& operator<<(ostream &out,Person ob ){out<<ob.num<<" "<<ob.name<<" "<<ob.score;return out;
}
istream &operator>>(istream &in,Person &ob){
in>>ob.num>>ob.name>>ob.score;
return in;
}int main(int argc, char *argv[])
{Person lucy(100,"lucy", 88.8f);Person bob;//先使用后++bob = lucy++;cout<<bob<<endl;cout<<lucy<<endl;return 0;
}
案例2:重载前置++
#include <iostream>
#include<string>
using namespace std;
class Person{friend ostream& operator<<(ostream &out,Person ob );friend istream& operator>>(istream &in,Person &ob);
private:int num;string name;float score;
public:Person(){}Person(int num,string name,float score):num(num),name(name),score(score){}Person operator +(Person ob2){Person temp;temp.num=this->num+ob2.num;temp.name=this->name+ob2.name;temp.score=this->score+ob2.score;return temp;}bool operator ==(Person &ob){if(num==ob.num&&name==ob.name&&score==ob.score){return true;}else{return false;}}Person operator ++(int a){Person old;old.num=num;old.name=name;old.score=score;num+=1;name+=name;score+=score;return old;}
//前置++Person operator ++(){num+=1;name+=name;score+=score;return *this;//返回自身的值}};
//返回cout的引用类型(可以链式输出)
ostream& operator<<(ostream &out,Person ob ){out<<ob.num<<" "<<ob.name<<" "<<ob.score;return out;
}
istream &operator>>(istream &in,Person &ob){
in>>ob.num>>ob.name>>ob.score;
return in;
}int main(int argc, char *argv[])
{Person lucy(100,"lucy", 88.8f);Person bob;//先++ 后使用bob = ++lucy;cout<<bob<<endl;cout<<lucy<<endl;// bob等于lucyreturn 0;
}

8、重载()运算符
重载()运算符 一般用于 为算法 提供策略。
#include <iostream>
using namespace std;
class Print{
public:void operator()(char *str){cout<<str<<endl;}};int main()
{Print ob;//对象和()结合 触发operator()成员函数 调用ob("Hello World");//匿名成员Print()("hello world");return 0;
}
二、自定义string类
重载构造函数
#include <iostream>
#include<string.h>
using namespace std;class MyString{private:int size;char *str;
public:MyString();//无参构造MyString(char *str);//带参构造MyString(const MyString &ob);//深拷贝~MyString();//析构函数
};MyString::MyString(){str=NULL;size=0;
}
MyString::MyString(char *str){size=strlen(str);this->str=new char[size+1];memset(this->str,0,size+1);strcpy(this->str,str);
}MyString::MyString(const MyString &ob){size=ob.size;str=new char[size+1];memset(str,0,size+1);strcpy(str,ob.str);}MyString::~MyString(){if(str!=NULL){delete[]str;str=NULL;}
}int main(int argc, char *argv[])
{return 0;
}
重载输入输出(全局函数实现)
设为友元函数
friend ostream& operator<<(ostream &out,MyString ob);
friend istream& operator >>(istream &in,MyString &ob);
全局函数实现
ostream& operator<<(ostream &out,MyString ob){out<<ob.str;return out;
}
istream& operator >>(istream &in,MyString &ob){char buff[1024]="";cin>>buff;if(ob.str!=NULL){delete[]ob.str;ob.str=NULL;}ob.size=strlen(buff);ob.str=new char[ob.size+1];memset(ob.str,0,ob.size+1);strcpy(ob.str,buff);return in;
}
重载括号运算符

类中声明,类外定义
char& MyString::operator [](int pos){if(pos<0||pos>=size){cout<<"元素位置不合法"<<endl;exit(-1);}return str[pos];}
重载+运算符

类外实现
MyString MyString::operator +(MyString ob){MyString temp;temp.size=size+ob.size;temp.str=new char[temp.size+1];memset( temp.str,0,temp.size+1);strcpy(temp.str,str);strcat(temp.str,ob.str);return temp;}MyString MyString::operator +(char *str){MyString temp;temp.size=this->size+strlen(str);temp.str=new char[temp.size+1];memset(temp.str,0,temp.size+1);strcpy(temp.str,this->str);strcat(temp.str,str);return temp;}
重载=赋值运算符(深拷贝)

MyString &MyString::operator =(MyString ob){if(this->str!=NULL){delete[]this->str;this->str=NULL;}this->size=ob.size;this->str=new char[this->size+1];memset(this->str,0,this->size+1);strcpy(this->str,ob.str);return *this;}MyString &MyString::operator =(char *str){if(this->str!=NULL){delete[]this->str;this->str=NULL;}this->size=strlen(str);this->str=new char[this->size+1];memset(this->str,0,this->size+1);strcpy(this->str,str);return *this;}
重载>运算符

bool MyString::operator>(MyString ob){if(str==NULL||ob.str==NULL){exit(-1);}if(strcmp(this->str,ob.str)>0){return true;}else{return false;}}bool MyString::operator >(char *str){if(str==NULL||this->str==NULL){exit(-1);}if(strcmp(this->str,str)>0){return true;}else{return false;}}
三、智能指针
智能指针:解决 堆区空间的对象释放问题
前言:
#include <iostream>
using namespace std;
class Data{
public:Data(){cout<<"无参构造"<<endl;}~Data(){cout<<"析构函数"<<endl;}void func(){cout<<"func函数"<<endl;}
};int main()
{Data *ob=new Data();//通过new申请堆区空间return 0;
}
结果:只打印了无参构造,并没有调用析构函数
无参构造
设置智能指针
#include <iostream>
using namespace std;
class Data{
public:Data(){cout<<"无参构造"<<endl;}~Data(){cout<<"析构函数"<<endl;}void func(){cout<<"func函数"<<endl;}
};class SmartPointer{private:Data *p;
public:SmartPointer(){}SmartPointer(Data *p){this->p=p;}~SmartPointer(){delete p;}};int main()
{SmartPointer ob(new Data);return 0;
}
无参构造
析构函数
结果是调用了析构函数,运用的原理就是生命周期
我们在类中
//重载*运算符Data& operator*(){return *p;}//重载->运算符Data* operator->(){return p;}
#include <iostream>
using namespace std;
class Data{
public:Data(){cout<<"无参构造"<<endl;}~Data(){cout<<"析构函数"<<endl;}void func(){cout<<"func函数"<<endl;}
};class SmartPointer{private:Data *p;
public:SmartPointer(){}SmartPointer(Data *p){this->p=p;}~SmartPointer(){delete p;}//重载*运算符Data& operator*(){return *p;}//重载->运算符Data* operator->(){return p;}};int main()
{SmartPointer ob(new Data);//访问通过SmartPointer访问pob.operator *().func();ob.operator->()->func();(*ob).func();ob->func();return 0;
}