目录
知识点1【运算符重载概述】
知识点2【可重载的运算符】
知识点3【运算符重载的步骤】
知识点4【重载运算符<<】
知识点5【重载>>运算符】
知识点6【重载==运算符】
知识点7【自增自减(++/--)运算符重载】
?知识点8【重载=赋值运算符】
?知识点9【重载 函数调用运算符 ()?】
知识点10【不要重载&& || 用户没办法实现短路特性?】(重要)
知识点11【不能重载的运算符】
知识点12【运算符重载案例】
知识点1【运算符重载概述】
运算符重载,就是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
比如:重载+运算符完成"lucy"+“bob”拼接
void operator+(参数1,参数2)
{
}
知识点2【可重载的运算符】
知识点3【运算符重载的步骤】
运算符重载分析步骤:
1、分析运算符左边的运算对象。如果不是自定义类的对象,只能用全局函数 实现运算符重载。
????????全局函数的第一参数:左边的运算对象,
????????全局函数的第二个参数:右边的运算对象
2、分析运算符左边的运算对象.如果是自定义类的对象,可以用全局函数、成员函数 实现运算符重载。
????????全局函数的第一参数:左边的运算对象,
????????全局函数的第二个参数:右边对象
成员函数:可以省略一个参数,只需要将运算符右边的对象 传递到成员函数中。(推荐)
知识点4【重载运算符<<】
#include <iostream>
#include <string>
using namespace std;
class Person
{
friend ostream& operator<<(ostream &out, Person &ob);
private:
int num;
string name;
int age;
public:
Person(){}
Person(int num, string name, int age)
{
this->num = num;
this->name = name;
this->age = age;
}
void showPerson(void)
{
cout<<"学号:"<<num<<", 姓名:"<<name<<", 年龄:"<<age<<endl;
}
};
//全局友元函数实现运算符重载
ostream& operator<<(ostream &out, Person &ob)
{
out<<"学号:"<<ob.num<<", 姓名:"<<ob.name<<", 年龄:"<<ob.age<<endl;
return out;
}
int main(int argc, char *argv[])
{
Person ob1(100,"lucy", 18);
Person ob2(101,"bob", 19);
cout<<ob1<<ob2<<endl;// operator<<(cout,ob1);
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;
int age;
public:
Person(){}
Person(int num, string name, int age)
{
this->num = num;
this->name = name;
this->age = age;
}
void showPerson(void)
{
cout<<"学号:"<<num<<", 姓名:"<<name<<", 年龄:"<<age<<endl;
}
};
//全局友元函数实现运算符重载
ostream& operator<<(ostream &out, Person &ob)
{
out<<"学号:"<<ob.num<<", 姓名:"<<ob.name<<", 年龄:"<<ob.age<<endl;
return out;
}
//全局友元函数实现运算符重载
istream& operator>>(istream &in, Person &ob)
{
in>>ob.num>>ob.name>>ob.age;
return in;
}
int main(int argc, char *argv[])
{
Person ob1(100,"lucy", 18);
Person ob2(101,"bob", 19);
cout<<ob1<<ob2<<endl;// operator<<(cout,ob1);
Person ob3;
cin>>ob3;
cout<<ob3;
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);
//friend bool operator==(Person &ob1, Person &ob2);
private:
int num;
string name;
int age;
public:
Person(){}
Person(int num, string name, int age)
{
this->num = num;
this->name = name;
this->age = age;
}
void showPerson(void)
{
cout<<"学号:"<<num<<", 姓名:"<<name<<", 年龄:"<<age<<endl;
}
//成员函数完成==重载
bool operator==(Person &ob)
{
if(num==ob.num && name==ob.name && age==ob.age)
return true;
else
return false;
}
};
//全局友元函数实现运算符重载
ostream& operator<<(ostream &out, Person &ob)
{
out<<"学号:"<<ob.num<<", 姓名:"<<ob.name<<", 年龄:"<<ob.age<<endl;
return out;
}
//全局友元函数实现运算符重载
istream& operator>>(istream &in, Person &ob)
{
in>>ob.num>>ob.name>>ob.age;
return in;
}
#if 0
//全局友元函数 实现==重载
bool operator==(Person &ob1, Person &ob2)
{
if(ob1.num==ob2.num && ob1.name==ob2.name && ob1.age==ob2.age)
return true;
else
return false;
}
#endif
int main(int argc, char *argv[])
{
Person ob1(100,"lucy", 18);
Person ob2(101,"bob", 19);
cout<<ob1<<ob2<<endl;// operator<<(cout,ob1);
Person ob3;
cin>>ob3;
cout<<ob3;
//ob1.operator==(ob2);
if(ob1 == ob2)
{
cout<<"相等"<<endl;
}
else
{
cout<<"不相等"<<endl;
}
return 0;
}
知识点7【自增自减(++/--)运算符重载】
当编译器看到 ++a? ?(前置++),它就调用operator++(a),
当编译器看到 a++? ?(后置++),它就会去调用operator++(a,int)
全局函数实现:
????????++ob ------------->operator++(ob)
????????ob++ ------------->operator++(ob, int)
成员函数实现:
????????++ob ------------->ob.operator++()
????????ob++ ------------->ob.operator++(int)
#include <iostream>
using namespace std;
class Data
{
friend ostream& operator<<(ostream &out, Data ob);
private:
int a;
int b;
public:
Data(){}
Data(int a, int b):a(a),b(b){}
//重载ob++ 先使用 后加减
Data operator++(int)
{
//保存++之前的值
Data tmp = *this;
//进行自增
a = a+1;
b = b+1;
return tmp;//返回++之前的值
}
//重载++ob 先加减 后使用
Data operator++()
{
//先加减
a=a+1;
b=b+1;
//再使用
return *this;
}
};
ostream& operator<<(ostream &out, Data ob)
{
out<<"a="<<ob.a<<", b="<<ob.b<<endl;
return out;
}
int main(int argc, char *argv[])
{
Data ob1(10,20);
cout<<ob1<<endl;
cout<<ob1++<<endl;
cout<<ob1<<endl;
Data ob2(100,200);
cout<<ob2<<endl;
cout<<++ob2<<endl;
cout<<ob2<<endl;
return 0;
}
?知识点8【重载=赋值运算符】
(类中有指针成员 才需要重载=)
如果类中没有指针成员 相同类型的对象 可以直接=赋值(浅拷贝)
如果类中有指针成员 相同类型的对象 必须重载=(深拷贝)
#include<string.h>
class Data2
{
public:
char *str;//指针成员
public:
Data2(){}
Data2(char *str)
{
this->str = new char[strlen(str)+1];
strcpy(this->str, str);
}
~Data2()
{
if(str != NULL)
{
delete [] str;
str=NULL;
}
}
//重载=
Data2& operator=(Data2 &ob)
{
cout<<"重载="<<endl;
this->str = new char[strlen(ob.str)+1];
strcpy(this->str, ob.str);
return *this;
}
};
void test02()
{
Data2 ob1("hello world");
Data2 ob2;
Data2 ob3;
ob3 = ob2 = ob1;
cout<<ob2.str<<endl;
cout<<ob3.str<<endl;
}
总结:如果类中有指针成员
必须实现拷贝构造(深拷贝)、必须实现析够函数(释放指针成员所指向的空间)、必须重载=运算符(深拷贝)
?知识点9【重载 函数调用运算符 ()?】
class Print
{
public:
void operator()(char *str)
{
cout<<str<<endl;
}
};
void test03()
{
Print ob;
ob.operator ()("hello world");
//仿函数(本质 不是函数 只是像函数调用)
//对象名 与 ()结合 触发了operator()调用 (本质)
ob("hello beijing");
//Print()是Print类的匿名对象
Print()("hello qf");
}
8、不要重载&& || 用户没办法实现短路特性 (重要)
知识点10【不要重载&& || 用户没办法实现短路特性?】(重要)
知识点11【不能重载的运算符】
?
知识点12【运算符重载案例】
mystring.h
#ifndef MYSTRING_H
#define MYSTRING_H
#include<iostream>
using namespace std;
class MyString
{
friend ostream& operator<<(ostream &out, MyString ob);
private:
char *str;
int size;
public:
MyString();
MyString(char *str);
MyString(const MyString &ob);
~MyString();
//获取字符串的长度
int getSize(void);
//获取字符
char& operator[](int pos);
char& at(int pos);
//重载赋值运算符=
MyString& operator=(MyString &ob);
MyString& operator=(char *str);
//重载赋值运算符+=
MyString& operator+=(MyString &ob);
MyString& operator+=(char *str);
//重载+运算符
MyString operator+(MyString &ob);
// MyString operator+(char *str);
bool operator>(MyString &ob);
};
#endif // MYSTRING_H
myString.cpp
#include "mystring.h"
#include<string.h>
#include<iostream>
using namespace std;
MyString::MyString()
{
str=NULL;
size=0;
cout<<"无参构造"<<endl;
}
MyString::MyString(char *str)
{
size = strlen(str);
this->str = new char[size+1];
strcpy(this->str, str);
cout<<"有参构造"<<endl;
}
MyString::MyString(const MyString &ob)
{
size = ob.size;
str = new char[size +1];
strcpy(str, ob.str);
cout<<"拷贝构造函数"<<endl;
}
MyString::~MyString()
{
if(str != NULL)
{
delete [] str;
str = NULL;
}
cout<<"析够函数调用"<<endl;
}
int MyString::getSize()
{
return size;
}
char& MyString::operator[](int pos)
{
if(pos>=0 && pos<size)
{
return str[pos];
}
else
{
cout<<"坐标无效"<<endl;
}
}
char &MyString::at(int pos)
{
if(pos>=0 && pos<size)
{
return str[pos];
}
else
{
cout<<"坐标无效"<<endl;
}
}
MyString &MyString::operator=(MyString &ob)
{
//ob1 = ob
//先释放ob1.str指向的堆区空间
if(str != NULL)
{
delete [] str;
str=NULL;
}
size = ob.size;
str = new char[size+1];
strcpy(str, ob.str);
return *this;
}
MyString &MyString::operator=(char *str)
{
//先释放ob1.str指向的堆区空间
if(this->str != NULL)
{
delete [] this->str;
this->str=NULL;
}
size = strlen(str);
this->str = new char[size+1];
strcpy(this->str, str);
return *this;
}
MyString& MyString::operator+=(MyString &ob)
{
if((str==NULL) && (ob.str != NULL))
{
size = ob.size;
str = new char[size+1];
memset(str, 0,size+1);
strcpy(str, ob.str);
//记得返回
}
else if((str != NULL) && (ob.str == NULL))
{
//记得返回
}
else if((str == NULL) && (ob.str == NULL))
{
cout<<"全为NULL无法拼接"<<endl;
//记得返回
}
else if((str != NULL) && (ob.str != NULL))
{
//str7 += str8
//新空间的大小
size = size+ob.size;
char *tmp_str = new char[size+1];
//清空新空间的内容
memset(tmp_str, 0, size+1);
strcpy(tmp_str, str);
strcat(tmp_str, ob.str);
//释放str指向的空间
delete [] str;
str = tmp_str;
//记得返回
}
return *this;
}
MyString &MyString::operator+=(char *str)
{
if(this->str == NULL)
{
size = strlen(str);
this->str = new char[size+1];
memset(this->str, 0, size+1);
strcpy(this->str, str);
}
else if(this->str != NULL)
{
size = size+strlen(str);
char *tmp_str = new char[size+1];
memset(tmp_str, 0, size+1);
strcpy(tmp_str, this->str);
strcat(tmp_str, str);
//释放this->str指向的旧空间
delete [] this->str;
this->str = tmp_str;
}
return *this;
}
MyString MyString::operator+(MyString &ob)
{
if((this->str==NULL) && (ob.str == NULL))
{
cout<<"全空无法进行+运算"<<endl;
return *this;
}
else if((this->str!=NULL) && (ob.str == NULL))
{
return *this;
}
else if((this->str==NULL) && (ob.str != NULL))
{
return ob;
}
else if((this->str!=NULL) && (ob.str != NULL))
{
char *buf=new char[size+ob.size+1];
memset(buf, 0, size+ob.size+1);
strcpy(buf,this->str);
strcat(buf, ob.str);
MyString tmp(buf);
delete [] buf;
return tmp;
}
}
bool MyString::operator>(MyString &ob)
{
if((str != NULL) && (ob.str != NULL) )
{
if(strcmp(str, ob.str)>0)
{
return true;
}
else
{
return false;
}
}
else
{
cout<<"存在NULL字符串无法比较大小"<<endl;
}
return false;
}
//全局函数重载<<运算符
ostream& operator<<(ostream &out, MyString ob)
{
cout<<ob.str;
return out;
}
main.cpp
#include <iostream>
#include "mystring.h"
using namespace std;
int main(int argc, char *argv[])
{
#if 0
MyString str1("hello");
cout<<"str1的长度="<<str1.getSize()<<endl;
cout<<str1<<endl;
//获取str1的某个字符
str1[2] = 'W';
cout<<str1[2] <<endl;
str1.at(3)='H';
cout<<str1<<endl;
//对象赋值
MyString str2("hello");
MyString str3("world");
MyString str4("hehe");
str4 = str3 = str2;
cout<<str4<<endl;
//字符串 给对象赋值
MyString str5;
MyString str6;
str6 = str5 = "hello";
cout<<str6<<endl;
MyString str7("hello");
MyString str8("world");
str7 += str8;
cout<<str7<<endl;
MyString str9;
str9+="world";
cout<<str9<<endl;
#endif
MyString str10("hello");
MyString str11("world");
MyString str12("hehe");
cout<<(str10+str11+str12)<<endl;
if(str11 > str12)
{
cout<<"大于"<<endl;
}
else
{
cout<<"不大于"<<endl;
}
return 0;
}
?
|