运算符重载
- 运算符重载的概念
- 运算符重载
- 用友元实现运算符重载
运算符重载的概念
什么是运算符重载
重载,重新载入,比如函数重载,对一个已有的函数赋予一个新的定义,因此一个名字就能代表不同的含义。
运算符也是可以重载的,比如在cout时,能接受不同类型的数据并输出,这个就是运算符的重载。
因此,运算符重载,指的是对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型。
为什么要进行运算符重载
运算符重载,可以让运算符去适应不同的数据类型,对于基本数据类型,系统给出了运算符的操作规则,但对于自定义类型来说,系统是无法给出操作规则的。
// 如下:
Complex c3 = c2 + c1;
- Complex是用户自定义类类型(类或结构体)。
- 在这里两个自定义类型的变量,编译器根本不知道怎么去计算。
- 编译器提供了一种机制,让用户自己去完成,自定义类型的计算。
- 这个机制就是运算符重载。
运算符重载
运算符重载定义
关键字
operator,通过关键字修饰运算符来构成运算符重载
定义
函数返回值类型 operator运算符(参数列表)
{
函数体;
}
①返回值类型:这个运算符计算之后要返回一个什么值。
②operator运算符:表示运算符重载,也可以理解为一个函数名
③参数列表:这个运算符需要的操作数。
④函数体:这个运算符我们赋予他什么新的规则。
运算符重载特性
- 运算符重载,运算符重新定义新的操作规则。
- 几乎所有的运算符都可以被重载。 除以下:. :: ?: sizeof这些运算符之外。
- 运算符重载基本上出现在类中和结构中。
- 运算符重载要满足运算符原来的规则。
- 运算符理解为函数的一个表现。
常见运算符重载示例
class CMyCard
{
int val;
public:
int operator+(CMyCard const& mc)
{
return this->val + mc.val;
}
}mc1,mc2; //mc1,mc2为类对象
int cardVal; //整型变量
//直接调用的+号运算符,计算的是两个对象之和,把结果返回给到整型变量。
cardVal = mc1 + mc2;
//通过对象mc1点出成员运算符重载的函数,把mc2做为参数传递进去计算。也是把结果返回给整型变量。
cardVal = mc1.operator+(mc2);
分析:
示例中表现加号重载,重载让两个对象相加,加的是对象里面的私有成员val的
值,通过 int operator +(CMyCard const& mc) 这个函数体现出来。
在函数体内设定两个变量的相加,所以返回值可以是一个int类型的变量,也是
其他的,需要返回什么就可以返回一个什么。比如,可以返回一个CMyCard类型也是
常见操作。
基本大部分运算符重载都可参照该示例进行定义。
自增运算符重载示例
class CMyCard
{
int val;
public:
CMyCard& operator ++()//++前置
{
this->val++;
return *this;
}
};
<strong> ++前置,先自增,再返回,返回自身类型,返回值类型使用引用。
自增运算符重载示例
class CMyCard
{
int val;
public:
CMyCard operator ++(int)//++后置
{
CMyCard temp = *this;
this->val++;
return temp;
}
};
++后置,先返回,再自增,因此先用临时变量备份自身原来的数据,自身数据改变。返回临时对象。因为是临时对象,返回值类型不能使用引用。
运算符重载注意事项
- 运算符重载,是重新定义运算符的操作类型,该运算符原来能操作的类型是系统预先设置好的,通过运算符重载,可以加载用户需要操作的类型。
- 对于运算符重载的调用,可以直接使用运算符,也可以显示调用(通过类对象点出运算符)。
注意:显示调用需要该运算符操作属于该类。- 考虑参数列表,运算符需要和操作数一起组成表达式,参数列表就是用来表示操作数。
注意:运算符重载在类中,那么this指针所指的调用者对象也属于其中一个操作数。- 、考虑函数返回值,不同的运算符会有不同的返回,要满足运算符本来的规则。
用友元实现运算符重载
类已经实现且无法修改的情况下,需要进行运算符重载,就可以通过友元的方式来进行实现。
输入输出的运算符重载
class CMyCard
{
int val;
public:
friend istream >> (istream & is, CMyCard& mc);//输入
friend ostream << (ostream & os, CMyCard& mc);//输出
};
输入输出的运算符重载
//在类外定义
istream& >> (istream & is, CMyCard& mc)
{
is >> mc.val;
return is;
}
ostream& << (ostream & os, CMyCard& mc)
{
os << mc.val;
return os;
}
练习代码
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
class Person
{
private:
int id;
string name;
public:
Person operator +(const Person &p)
{
this->id += p.id;
this->name = this->name + p.name;
return *this;
}
Person &operator ++()
{
this->id += 1;
return *this;
}
Person operator ++(int)
{
Person p1 = *this;
this->id += 1;
return p1;
}
Person(int id, string name)
{
this->id = id;
this->name = name;
}
void get()
{
cout << "id:" << id << endl << "name:" << name << endl;
}
int Get()
{
return id;
}
~Person()
{
}
friend ostream& operator << (ostream& os, Person& p);
};
ostream& operator << (ostream& os,Person&p)
{
os << p.id;
return os;
}
class A
{
int id;
public:
A(int id)
{
this->id = id;
}
};
class smartpoint
{
Person* ps;
public:
smartpoint(Person* ps)
{
this->ps = ps;
}
Person* operator->()
{
return this->ps;
}
Person& operator*()
{
return *this->ps;
}
void fun()
{
cout << "fun函数" << endl;
}
~smartpoint()
{
if (ps != NULL)
{
delete ps;
ps = NULL;
}
cout << "智能指针释放了" << endl;
}
};
int main()
{
Person p(1, "Ye");
Person p1(2, "Sir");
p =p+ p1;
p.get();
p++;
p.get();
++p;
p.get();
cout << p << endl;
cout << endl;
{
smartpoint sp(new Person(1,"Yesir"));
sp->get();
sp.fun();
}
system("pause");
return 0;
}
智能指针
智能指针是一种托管资源空间的技术,可以访问空间、模拟原生指针的行为,只是在原生指针生命周期结束时,释放资源。
class smartpoint
{
Person* ps;
public:
smartpoint(Person* ps)
{
this->ps = ps;
}
Person* operator->()
{
return this->ps;
}
Person& operator*()
{
return *this->ps;
}
void fun()
{
cout << "fun函数" << endl;
}
~smartpoint()
{
if (ps != NULL)
{
delete ps;
ps = NULL;
}
cout << "智能指针释放了" << endl;
}
};
int main()
{
cout << endl;
//智能指针死亡, 调用析构, 在析构里释放Person申请的内存, 避免了内存泄漏的问题
{
smartpoint sp(new Person(1,"Yesir"));
sp->get();
sp.fun();
}
}
使用运算符重载实现string类的功能
//利用运算符重载实现string类的功能
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
using namespace std;
class String
{
char* str;
public:
String(const char* str)
{
this->str = new char[strlen(str) + 1];
strcpy(this->str, str);
}
void GetStr()
{
cout << str <<endl;
}
//获取长度
int lengt()
{
return strlen(str);
}
//拷贝
String(const String& s)
{
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
}
//拷贝两个
String(const String& s, const String& s1)
{
this->str = new char[strlen(s.str) + strlen(s1.str) + 1];
this->str = strcat(s.str, s1.str);
}
//拼接
char* operator+(String& s)
{
int len = strlen(this->str) + strlen(s.str);
char* data = new char[len+1];
data = strcat(this->str, s.str);
return data;
}
bool operator<(String& s)
{
return strlen(this->str) < strlen(s.str);
}
bool operator>(String& s)
{
return strlen(this->str) > strlen(s.str);
}
bool operator==(String& s)
{
return strlen(this->str) == strlen(s.str);
}
};
using namespace std;
int main()
{
String str("Yesir");
String str1("abcde");
String s = str + str1;
s.GetStr();
cout << (str < str1) << endl;
cout << (str > str1) << endl;
cout << (str == str1) << endl;
//cout << str + str1 << endl;
//string s2 = "Yesir";
//string s1 = "abc";
system("pause");
return 0;
}