我是靠谱客的博主 秀丽大米,最近开发中收集的这篇文章主要介绍C++复习笔记(二)之运算符重载,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

一、运算符重载的存在于意义

我们使用基础的数据类型int、 double、 float、 long 、long long 等数据类型可以进行加减乘除操作,但是复杂的数据类型我们就不能使用加减乘除进行运算了,比如类的对象,结构体等等。

因此c++编译器需要给我提供一种机制,可以让我们对复杂数据类型进行一个相加减或其他的运算符操作。

运算符重载可以是复杂的数据类型的运算符操作,变得简单易实现。

二、运算符重载的语法

语法: 类型 类名::operator 运算符(参数数表)

           {

                      运算符的操作

           }

本质:运算符重载的本质是函数调用

重载运算符函数可以对运算符左出新的解释、但是原有基础语义不变。

         1、不改变运算符的优先级

         2、不改变运算符的结合性

         3、不改变运算符所需要的操作数

         4、不能创建新的运算符

三、运算符重载的方法

1、运算符重载可以重载为成员函数和友员函数

2、成员函数有this指针,而友员函数为this指针,因此在使用友员函数实现重载时,函数的参数列表比成员函数多一个参数。

3、不论是成员函数还是友员函数实现运算符重载、运算符的使用方法相同。但是传递参数的方式不同,实现代码不同、应用场合也是不同的。

四、运算符重载的小陷阱

(一)实现后置++/--需要使用占位参数

当我们去实现++,-- 运算符时,分为了两种情况,一种是先进行++/-- 后进行值的抛出即 ++i/--i 的实现,另一种是实现i--/i++。以自增函数为例(++操作符实现),当我们需要将写++i的运算符重载是如下:

class B
{
public:
B(int a = 2)
{
this->a = a;
}
int getnum()
{
return this->a;
}
//类内的成员函数实现B++操作符重载;
B& operator++()
{
this->a++;
return *this;
}
protected:
private:
int a;
};
void main()
{
B a(5);
++a;
cout << a.getnum() << endl;
system("pause");
return;
}

但是上面仅仅只是实现了前置++操作,但我们进行后置++操作时依然会报错。此时我们的后置++也需要重载操作

	//类内的成员函数实现++B操作符重载;
B& operator++()
{
B tmp = this;
this->a++;
return tmp;
}

根据函数重载的定义,只有函数的参数才是函数重载的标志。因此c++编译器在遇见++操作时,不知道用哪一个函数,就会报错,所以我们默认规定当重载后置++操作符时,其重载函数需要使用占位参数,以和前置++区分开来。

class B
{
public:
B(int a = 2)
{
this->a = a;
}
B(B &iteam)
{
this->a = iteam.a;
}
int getnum()
{
return this->a;
}
//类内的成员函数实现B++操作符重载;
B& operator++()
{
this->a++;
return *this;
}
//类内的成员函数实现++B操作符重载,使用占位参数;
B& operator++(int)
{
B tmp = *this;
this->a++;
return tmp;
}
protected:
private:
int a;
};
void main()
{
B a(5);
++a;
B a1 = a++;
cout << a.getnum() << endl;
cout << a1.getnum() << endl;
system("pause");
return;
}

(二)友员函数与成员函数实现重载的场景与局限

友员函数的特性,使得它非常适合用来实现操作符重载,但是友员函数实现操作符重载最好使用在下面场景

1、当无法修改左操作数的类是需要使用到友员函数进行重载,例如重载左移操作符“<<”和右移操作符">>",不能使用成员函数。

2、当运算符则左右操作数类型不相等的时候可以使用友员函数来重载,比如:int+classobject,这个种情况下就需要使用友员函数重载+号,因为int类型是无法调用类的方法的,clasobject可以调用类的方法,int类型不能,不能使用成员函数实现。

3、友员函数无法实现()、[ ]、 =  、->重载操作。

五、不要重载 || 和 &&

虽然我们可以实现重载|| 和 && 符号,但是因为这个两个符号有短路规则,是我们无法重载的,尽量不要去重载 || 和 && 。

短路规则: 例如: a==1 && b==1 只要a==1 为假,c++编译器就会去判断b == 1 是否为真,直接判定整个表达式为假;只有当a ==1判定为真的时候,c++编译器才会去判断b==1是否为假。

六、运算符重载的练习

使用运算符重载机制,和类的机制,去实现一个字符串类。

字符串类的定义:

class Mystring
{
public:
Mystring(int len);
Mystring(char *p);
Mystring(Mystring &item);
char &operator[](int i);
//重载[]
Mystring &operator=(const char *p);
//实现对象与字符串的深拷贝
Mystring &operator=(Mystring &item); //实现对象之间的深拷贝
Mystring operator+(Mystring &item);
//两个对象相加的操作符实现
friend Mystring operator+(Mystring &item, const char *p);
friend Mystring operator+(const char *p, Mystring &item);
//友员函数实现对象与char类型相加
friend istream &operator>>(istream &in, Mystring &item);
friend ostream &operator<<(ostream &out,Mystring &item);
~Mystring();
private:
int len;
char *str;
};

类方法的实现:

 

#include<iostream>
using namespace std;
Mystring::Mystring(int len=0)
{
if (len == 0)
{
this->len = 0;
this->str = new char[this->len + 1];
strcpy(this->str, "");
}
else
{
this->len = len;
this->str = new char[this->len + 1];
memset(this->str, '0', this->len+1);
}
}
Mystring::Mystring(char *p)
{
if (p!=NULL)
{
this->len = strlen(p);
this->str = new char[this->len + 1];
strcpy(this->str, p);
}
else
{
this->len = 0;
this->str = new char[this->len+1] ;
strcpy(this->str, "");
}
}
Mystring::Mystring(Mystring &item)
{
this->len = item.len;
this->str = new char[this->len + 1];
strcpy(this->str, item.str);
}
Mystring::~Mystring()
{
if (this->str)
{
delete[] this->str;
this->len = 0;
this->str = NULL;
}
}
char &Mystring::operator[](int i)
{
if (i<this->len)
{
return (this->str[i]);
}
}
Mystring & Mystring::operator=(const char *p)
{
if (this->str !=NULL)
{
delete[] this->str;
this->str = NULL;
this->len = 0;
}
if (p != NULL)
{
this->len = strlen(p);
this->str = new char[this->len + 1];
strcpy(this->str, p);
}
else
{
this->len = 0;
this->str = new char[this->len + 1];
strcpy(this->str, "");
}
return *this;
}
Mystring & Mystring::operator=(Mystring &item)
{
//将原来内存析构掉
if (this->str!=NULL)
{
delete[] this->str;
this->str = NULL;
this->len = 0;
}
//重新分配内存
this->len = item.len;
this->str = new char[this->len + 1];
strcpy(this->str, item.str);
return *this;
}
//因为需要返回一个栈变量,所以返回对象元素比返回一个引用更合适
//返回元素对象会生成一个的匿名对象进行返回。
//而返回引用,因为strtmp是一个栈变量所以会报错。
Mystring Mystring::operator+(Mystring &item)
{
Mystring strtmp(this->len + item.len);
strcpy(strtmp.str, this->str);
strcat(strtmp.str, item.str);
strtmp.len = strlen(strtmp.str);
return strtmp;
}
Mystring operator+(Mystring &item,const char *p)
{
if (p)
{
Mystring strtmp(item.len + strlen(p));
strcpy(strtmp.str, item.str);
strcat(strtmp.str, p);
strtmp.len = strlen(strtmp.str);
return strtmp;
}
else
{
return item;
}
}
Mystring operator+(const char *p,Mystring &item)
{
if (p)
{
Mystring strtmp(item.len + strlen(p));
strcpy(strtmp.str, item.str);
strcat(strtmp.str, p);
strtmp.len = strlen(strtmp.str);
return strtmp;
}
else
{
return item;
}
}
istream &operator>>(istream &in, Mystring &item)
{
in >> item.str;
return in;
}
ostream &operator<<(ostream &out, Mystring &item)
{
out << item.str;
return out;
}

 

最后

以上就是秀丽大米为你收集整理的C++复习笔记(二)之运算符重载的全部内容,希望文章能够帮你解决C++复习笔记(二)之运算符重载所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(68)

评论列表共有 0 条评论

立即
投稿
返回
顶部