运算符重载: operator关键字用来重载运算符
1、概念
1)本质是一个函数,函数名的组成方式是:operator + 要重载的运算符
运算符的重载函数可以写到类的内部,但内外只能有一个(尽量写内部,内外的实现方式由于传参方式不同实现代码不同在一些复杂的运算时会有不同)
2)有部分运算符不能重载 . :: .* ?: sizeof
3)重载步骤:首先写出函数名,再根据运算需要写出函数的参数列表以及函数的返回值类型
2、友元函数实现操作符重载
1)当我们无法修改左操作数的类时,需要使用全局函数进行重载;
2)部分操作符只能通过成员函数进行重载 = [] () ->
3)<< 操作符由于拿不到 cout 这个类的源码,使用类成员函数无法实现重载,只能使用友元函数
4)友元函数重载运算符常用于运算符的左右操作数类型不同的情况,像+运算符,就不能实现整数+类的写法,整数.operator+(z)是不存在的。
3、部分运算符的重载实现
1)赋值运算符 = 用于对象数据的复制
如果没有定义赋值运算符的重载,编译器会有自己默认的赋值运算符,但默认的赋值运算符做的浅拷贝,所以和拷贝构造类似,赋值运算符的重载也需要自己写。赋值的实现过程基本可以分为这几步:释放旧空间,开辟新空间,复制。当然,在这之前需要加上一个是不是自己对自己赋值的判断2)括号运算符 ()
t(10) ===> t.opertaor()(int num) 这样的重载方式可以实现伪函数3)下标运算符 [] 用来访问数据对象的元素
x[y] ===> t.operator[](y)
4)与操作和或操作 && ||
&& 和|| 的内部实现了短路规则,但操作符重载是靠函数重载来实现的,操作数作为函数参数传递,而C++中函数的参数会被求值,无法实现短路规则。
4、数组与字符串的封装:利用上述的规则可以实现数组与字符串的封装,需要注意的点有:
1)传参时要注意参数类型,像字符串的类型为 const char *。
2)用new开辟空间时,要注意长度为(strlen(str)+1),要算上'\0'。
下面贴上部分实现代码:
头文件:Mystring.h
#ifndef __MYSTRING_H__
#define __MYSTRING_H__
#include <iostream>
class MyString
{
friend std::ostream &operator<<(std::ostream &out, const MyString &obj);
friend std::istream &operator>>(std::istream &in, MyString &obj);
public:
MyString(); // 无参构造
MyString(const char *); // 一个参数(字符串常量)构造函数
MyString(const MyString &str); // 拷贝构造
~MyString(); // 析构函数
public:
MyString& operator=(const char *s); // '= '的重载(参数为字符串常量)
MyString& operator=(const MyString &obj); // '= '的重载(参数为类)
char & operator[](int index); // '[]'的重载
MyString &operator+(const char *str); // '+ '的重载
MyString &operator+(const MyString &obj);
MyString& operator+=(const char *str); // '+= '的重载
MyString& operator+=(const MyString &obj);
bool operator==(const char *str) const; // '== '的重载
bool operator==(const MyString &obj) const;
bool operator>(const char *str) const; // '> ' 的重载
bool operator>(const MyString &obj) const;
bool operator<(const char *str) const; // '< ' 的重载
bool operator<(const MyString &obj) const;
public:
const char *c_str()
{
return m_p;
}
char *c_str2()
{
return m_p;
}
private:
char *m_p;
};
#endif // __MYSTRING_H__
函数实现:MyString.cpp
#include "MyString.h"
#include <string.h>
std::ostream &operator<<(std::ostream &out, const MyString &obj)
{
out << obj.m_p;
return out;
}
std::istream &operator>>(std::istream &in, MyString &obj)
{
in >> obj.m_p;
return in;
}
// ""
MyString::MyString()
{
m_p = new char[1];
m_p[0] = '\0';
}
MyString::MyString(const char *str)
{
if (str == NULL)
{
m_p = new char[1];
m_p[0] = '\0';
}
else
{
int len = strlen(str);
m_p = new char[len+1];
strcpy(m_p, str);
}
}
MyString::MyString(int len, char ch)
{
m_p = new char[len+1];
memset(m_p, ch, len);
}
MyString::MyString(const MyString &str)
{
if (str.m_p == NULL)
{
m_p = new char[1];
m_p[0] = '\0';
}
else
{
int len = strlen(str.m_p);
m_p = new char[len+1];
strcpy(m_p, str.m_p);
}
}
MyString::~MyString()
{
if (m_p != NULL)
{
delete[] m_p;
m_p = NULL;
}
}
MyString & MyString::operator=(const char *str)
{
if (m_p == str)
return *this;
if (m_p != NULL)
{
delete [] m_p;
m_p = NULL;
}
m_p = new char[strlen(str)+1];
char *tmp = m_p;
strcpy (m_p,tmp);
delete [] tmp;
return *this;
}
MyString &MyString::operator=(const MyString &obj)
{
*this = str.m_p;
return *this;
}
char & MyString::operator[](int index)
{
return m_p[index];
}
MyString & MyString::operator+(const char *str)
{
if(str == NULL)
return *this;
int len = strlen(m_p) + strlen(str);
char *tmp = m_p;
m_p = new char[len+1];
strcpy (m_p, tmp);
strcat (m_p, str);
delete[] tmp;
return *this;
}
MyString &MyString::operator+(const MyString &obj)
{
*this = *this + str.m_p;
return *this;
}
MyString & MyString::operator+=(const char *str)
{
return (*this + str);
}
MyString &MyString::operator+=(const MyString &obj)
{
return (*this + str.m_p);
}
bool MyString::operator==(const char *str) const
{
if (strcmp(str,m_p) != 0)
{
return false;
}
return true;
}
bool MyString::operator==(const MyString &obj) const
{
//return (m_p == (const char *) obj.m_p);
if (strcmp(m_p,obj.m_p) != 0)
{
return false;
}
return true;
}
bool MyString::operator>(const char *str) const
{
if (strcmp(m_p,str) > 0)
{
return true;
}
return false;
}
bool MyString::operator>(const MyString &obj) const
{
if (strcmp(m_p,obj.m_p) > 0)
{
return true;
}
return false;
}
bool MyString::operator<(const char *str) const
{
if (strcmp(m_p,str) < 0)
{
return true;
}
return false;
}
bool MyString::operator<(const MyString &obj) const
{
if (strcmp(m_p,obj.m_p) < 0)
{
return true;
}
return false;
}