一、简介
运算符的重载,实际是一种特殊的函数重载,必须定义一个函数,并告诉C++编译器,当遇到该运算符时就调用此函数来行使运算符功能。这个函数叫做运算符重载函数(常为类的成员函数)。用函数的方式实现了(+ - * / []数组 && || 逻辑 等)运算符的重载。
二、算数运算符的重载
class test8
{
//声明c_score为私有成员,所以要声明友元函数
//+ - * / 一个道理,这里只对 + - 进行演示
//重写了很多,是为了能够实现不同的应用场景
friend test8& operator-(test8& t, float score);
friend test8& operator-(float score, test8& t);
friend test8& operator-(test8& t1, test8& t2);
private:
float c_score;
public:
test8& test8::operator+(float score);
}
//!通过成员函数实现运算符重载,能够实现 t+2+5+6的运算
test8& test8::operator+(float score) {
//!if (this == nullptr) return; 不知道return啥
c_score += score;
return *this;
}
//!通过全局函数实现运算符重载
//可以实现 t - 2 - 3
test8& operator-(test8 &t,float score) {
t.c_score -= score;
return t;
}
//可以实现 52 - 41 -t
test8& operator-(float score, test8 &t) {
t.c_score -= score;
return t;
}
//可以实现 t - 20 - t
test8& operator-(test8& t1, test8& t2) {
t1.c_score -= t2.c_score;
return t1;
}
三、比较运算符的重载
返回值一定是bool
class test8
{private:
float c_score;
//重载 == < > != >= <=
bool operator==(const test8& t) {
if (c_score == t.c_score)return true;
return false;
}
四、下标运算符的重载
返回对象一定是string&类型
class test8
{private:
string c_boys[3];
//!下标运算符的重载
//非常对象用的函数
string& operator[](int i) {
return c_boys[i];
}
五、赋值运算符的重载
若不重写赋值运算符,系统会提供一个浅拷贝的赋值,这里作者写了一个提供深拷贝的赋值
class test8
{
public:
string c_name;
int c_age;
private:
float c_score;
string c_boys[3];
//!重载赋值运算符
test8& operator=(test8 g) {
if (this == &g) return *this;//代表自己给自己赋值
c_age = g.c_age;
c_name = g.c_name;
c_score = g.c_score;
if (g.c_ptr == nullptr) {
if(c_ptr != nullptr){
delete c_ptr;
c_ptr = nullptr;
}
}
else {
if (c_ptr == nullptr) {
c_ptr = new int;
}
memcpy(c_ptr, g.c_ptr, sizeof(int));
}
return *this;
}
六、左移运算符的重载
class test8
{
public:
string c_name;
int c_age;
private:
float c_score;
string c_boys[3];
}
//!对<<进行重载实现自定义类的输出,只能使用全局函数实现
ostream& operator<<(ostream& cout, test8& t) {
cout << "--> c_name " << t.c_name << endl;
cout << "--> c_age " << t.c_age << endl;
cout << "--> c_score " << t.c_score << endl;
cout << "--> c_ptr " << t.c_ptr << endl;
cout << endl;
return cout;
}
七、new和delete的重载写法固定
class test8
{
public:
string c_name;
int c_age;
//!重载new运算符,固定的写法
void* operator new(size_t size) {
cout << "调用了类的new函数" << endl;
void* ptr = malloc(size);
cout << "申请到的内存地址是 " << ptr << endl;
return ptr;
}
//!重载delete运算符
void operator delete(void* ptr) {
cout << "调用了类的delete函数" << endl;
if (ptr == 0) return;
free(ptr);
}
private:
float c_score;
string c_boys[3];
}
八、一元运算符的重载
常见的一元运算符有:
- 递增和递减运算符:++ 和 --,用于对操作数进行增加或减少 1。
- 正负号运算符:+ 和 -,用于表示正负数。
- 逻辑非运算符:!,用于对布尔值进行取反。
以++运算符为例子讲解,未重载++运算符可以实现的功能,想必大家都很熟悉,代码如下:
int main() {
int a1,a2;
a1 = 0;
a2 = 0;
int b = a1++;
int c = ++(++a2);
cout << "-->a1: " << a1 <<" -->b "<<b << endl;
cout << "-->a2: " << a2 <<" -->c "<<c << endl;
return 0;
}
运行结果,具体实现流程就不讲解了。
让我们来看++的重载,注意一元运算符的重载只能在成员函数中进行代码如下:
class test11 {
public:
int c_rank;
//使用初始化列表对c_rank进行初始化
test11() :c_rank(0) {
}
//重载++运算符
void operator++() {
c_rank += 1;
}
};
//重载<<运算符实现输出
ostream& operator<<(ostream& cout,const test11& t) {
cout << " -->c_rank " << t.c_rank << endl;
return cout;
}
int main() {
test11 a,b;
++a;
cout << a;
return 0;
}
运行结果
我们知道,++作为自增运算符是有前后顺序切可以反复执行的,上面的代码只是初始版,如果写出反复执行这样就可以这样改:
test11& operator++() {
c_rank += 1;
return *this;
}
就可以实现以下代码
++(++(++a))
对于后++,c++规定如果在传参列表中添加int代表后++,可以添加如下代码实现后++,且后++还可以反复执行:
test11& operator++(int) {
c_rank += 1;
return *this;
}
那么问题来了,后++的规则是先赋值再++,那么我们添加如下代码就可以实现后++的功能:
注意的是,成员函数中的临时对象是不能引用的,所以返回值不能是test11&类型,而是test11
test11 operator++(int) {
test11 tmp;
tmp = *this;
c_rank += 1;
return tmp;
}
九、总结
1.运算符号重载 返回值 operator运算符(形参列表);
2.运算符重载可以使用全局函数,也可以用成员函数,建议用成员函数 其中 = () [] ->只可以用成员函数重载
3.运算符重载形参的顺序是一定的,要是改变运输的顺序则需要进行再次重载
4.返回值是当前对象的引用
5.关系运算符的重载,可以对自定义的类进行比较
6..对<<进行重载实现自定义类的输出,只能使用全局函数实现
7.对new和delete进行重载时,若在类中,则作用域是类,写为全局函数,则作用域是全部