使用 成员函数 实现 等于判断 == 运算符重载 :
operate==
;operate==
operator==(String & s)
bool operator==(String& s)
// 重载 双等号 == 运算符
bool String::operator==(String& s)
{
// 首先判断数组长度是否相等
if (this->m_len != s.m_len)
{
return false;
}
for (size_t i = 0; i < this->m_len; i++)
{
// 只要有一个元素不相等, 整个数组就不相等
if (this->m_p[i] != s.m_p[i])
{
return false;
}
}
return true;
}
使用 成员函数 实现 重载 不等号 != 运算符 :
operate!=
;operate!=
operator!=(String& a)
bool operator!=(String& s)
// 重载 不等号 != 运算符
bool String::operator!=(String& s)
{
// 首先判断数组长度是否相等
if (this->m_len != s.m_len)
{
return false;
}
for (size_t i = 0; i < this->m_len; i++)
{
// 只要有一个元素不相等, 整个数组就不相等
if (this->m_p[i] != s.m_p[i])
{
return false;
}
}
return true;
}
#pragma once
#include "iostream"
using namespace std;
class String
{
public:
// 默认的无参构造函数
String();
// 有参构造函数 , 接收一个 char* 类型字符串指针
String(const char* p);
// 有参构造函数 , 接收 int 类型值 , 表示字符串大小
String(int len);
// 拷贝构造函数 , 使用 String 对象初始化 对象值
String(const String& s);
// 析构函数
~String();
public:
// 重载等号 = 操作符 , 右操作数是 String 对象的情况
String& operator=(const String& s);
// 重载等号 = 操作符 , 右操作数是 字符串常量值 的情况
String& operator=(const char* p);
// 重载 数组下标 [] 操作符
char& operator[](int i);
// 重载 双等号 == 运算符
bool operator==(String& s);
// 重载 不等号 != 运算符
bool operator!=(String& s);
// 使用 全局函数 实现 左移运算符 << 重载
// 将全局函数 声明为 String 的友元函数
friend ostream& operator<<(ostream& out, String& s);
public:
// 获取私有成员 char* m_p
char* str();
// 获取私有成员 int m_len
int len();
private:
// 字符串长度 , 不包括 '\0'
// 内存占用空间大小 = 字符串长度 + 1
int m_len;
// 字符串指针, 指向堆内存中的字符串
char* m_p;
};
// 使用 strcpy 函数报错
// error C4996: 'strcpy': This function or variable may be unsafe.
// Consider using strcpy_s instead.
// To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
// See online help for details.
#define _CRT_SECURE_NO_WARNINGS
#include "String.h"
// 默认的无参构造函数
String::String()
{
// 默认构造一个空字符串 , 字符串长度为 0
// 但是 , 字符串指针 指向的内存空间大小是 1 , 内容是 '\0'
m_len = 0;
// 使用 new 关键字为 char* m_p; 指针分配内存
// 对于基础数据类型 new 等同于 malloc
m_p = new char[m_len + 1];
// 拷贝空字符串到 m_p 指向的内存中
strcpy(m_p, "");
cout << "调用无参构造函数" << endl;
}
// 有参构造函数 , 接收一个 char* 类型字符串指针
String::String(const char* p)
{
if (p == NULL)
{
// 默认构造一个空字符串 , 字符串长度为 0
// 但是 , 字符串指针 指向的内存空间大小是 1 , 内容是 '\0'
this->m_len = 0;
// 使用 new 关键字为 char* m_p; 指针分配内存
// 对于基础数据类型 new 等同于 malloc
this->m_p = new char[this->m_len + 1];
// 拷贝空字符串到 m_p 指向的内存中
strcpy(this->m_p, "");
}
else
{
// 获取传入字符串的长度
// 但是 , 字符串指针 指向的内存空间大小需要 +1 , 内容是 '\0'
this->m_len = strlen(p);
// 使用 new 关键字为 char* m_p; 指针分配内存
// 对于基础数据类型 new 等同于 malloc
this->m_p = new char[this->m_len + 1];
// 拷贝字符串到 m_p 指向的内存中
strcpy(this->m_p, p);
}
cout << "调用有参构造函数" << endl;
}
// 有参构造函数 , 接收 int 类型值 , 表示字符串大小
String::String(int len)
{
if (len == 0)
{
// 默认构造一个空字符串 , 字符串长度为 0
// 但是 , 字符串指针 指向的内存空间大小是 1 , 内容是 '\0'
this->m_len = 0;
// 使用 new 关键字为 char* m_p; 指针分配内存
// 对于基础数据类型 new 等同于 malloc
this->m_p = new char[this->m_len + 1];
// 拷贝空字符串到 m_p 指向的内存中
strcpy(this->m_p, "");
}
else
{
// 获取传入字符串的长度
// 但是 , 字符串指针 指向的内存空间大小需要 +1 , 内容是 '\0'
this->m_len = len;
// 使用 new 关键字为 char* m_p; 指针分配内存
// 对于基础数据类型 new 等同于 malloc
this->m_p = new char[this->m_len + 1];
// 将内存空间设置为 0 内容
memset(this->m_p, 0, this->m_len);
}
};
// 拷贝构造函数 , 使用 String 对象初始化 对象值
String::String(const String& s)
{
// 拷贝字符串长度
// 注意 : 字符串指针 指向的内存空间大小需要 +1 , 内容是 '\0'
this->m_len = s.m_len;
// 使用 new 关键字为 char* m_p; 指针分配内存
// 对于基础数据类型 new 等同于 malloc
this->m_p = new char[this->m_len + 1];
// 拷贝字符串到 m_p 指向的内存中
strcpy(this->m_p, s.m_p);
cout << "调用拷贝构造函数" << endl;
}
// 析构函数
String::~String()
{
if (this->m_p != NULL)
{
// 之前使用 new 分配的内存
// 释放内存就需要使用 delete
// 使用 malloc 分配的内存需要使用 free 释放
delete[] this->m_p;
// 设置指针指为空 , 避免出现野指针
this->m_p = NULL;
// 设置字符串长度为 0
this->m_len = 0;
}
}
// 重载等号 = 操作符 , 右操作数是 String 对象的情况
String& String::operator=(const String& s)
{
// 先处理本对象已分配的内存
if (this->m_p != NULL)
{
// 之前使用 new 分配的内存
// 释放内存就需要使用 delete
// 使用 malloc 分配的内存需要使用 free 释放
delete[] this->m_p;
// 设置指针指为空 , 避免出现野指针
this->m_p = NULL;
// 设置字符串长度为 0
this->m_len = 0;
}
// 拷贝字符串长度
// 注意 : 字符串指针 指向的内存空间大小需要 +1 , 内容是 '\0'
this->m_len = s.m_len;
// 使用 new 关键字为 char* m_p; 指针分配内存
// 对于基础数据类型 new 等同于 malloc
this->m_p = new char[this->m_len + 1];
// 拷贝字符串到 m_p 指向的内存中
strcpy(this->m_p, s.m_p);
cout << "调用重载 等号 = 操作符函数 String& String::operator=(const String& s)" << endl;
return *this;
}
// 重载等号 = 操作符 , 右操作数是 字符串常量值 的情况
String& String::operator=(const char* p)
{
// 先处理本对象已分配的内存
if (this->m_p != NULL)
{
// 之前使用 new 分配的内存
// 释放内存就需要使用 delete
// 使用 malloc 分配的内存需要使用 free 释放
delete[] this->m_p;
// 设置指针指为空 , 避免出现野指针
this->m_p = NULL;
// 设置字符串长度为 0
this->m_len = 0;
}
// 拷贝字符串长度
// 注意 : 字符串指针 指向的内存空间大小需要 +1 , 内容是 '\0'
this->m_len = strlen(p);
// 使用 new 关键字为 char* m_p; 指针分配内存
// 对于基础数据类型 new 等同于 malloc
this->m_p = new char[this->m_len + 1];
// 拷贝字符串到 m_p 指向的内存中
strcpy(this->m_p, p);
cout << "调用重载 等号 = 操作符函数 String& String::operator=(const char* p)" << endl;
return *this;
}
// 重载 数组下标 [] 操作符
char& String::operator[](int i)
{
cout << "调用重载 下标 [] 操作符函数 char& String::operator[](int i)" << endl;
// 直接返回对应 i 索引字符
return this->m_p[i];
}
// 重载 双等号 == 运算符
bool String::operator==(String& s)
{
// 首先判断数组长度是否相等
if (this->m_len != s.m_len)
{
return false;
}
for (size_t i = 0; i < this->m_len; i++)
{
// 只要有一个元素不相等, 整个数组就不相等
if (this->m_p[i] != s.m_p[i])
{
return false;
}
}
return true;
}
// 重载 不等号 != 运算符
bool String::operator!=(String& s)
{
// 首先判断数组长度是否相等
if (this->m_len != s.m_len)
{
return false;
}
for (size_t i = 0; i < this->m_len; i++)
{
// 只要有一个元素不相等, 整个数组就不相等
if (this->m_p[i] != s.m_p[i])
{
return false;
}
}
return true;
}
// 获取私有成员 char* m_p
char* String::str()
{
return this->m_p;
}
// 获取私有成员 int m_len
int String::len()
{
return this->m_len;
}
// 全局函数 中实现 String 左移运算符重载
// 返回 ostream& 引用类型 , 是为了支持链式调用 cout << s1 << endl;
ostream& operator<<(ostream& out, String& s)
{
cout << "调用重载 左移 << 操作符函数 ostream& operator<<(ostream& out, String& s)" << endl;
// 在函数体中将 String 对象的 m_p 指针指向的数据输出到 out 输出流中
out << s.m_p << endl;
// 该返回值还需要当左值使用
return out;
}
#include "iostream"
using namespace std;
// 导入自定义的 String 类
#include "String.h"
int main() {
// 调用无参构造函数
String s1;
// 调用有参构造函数
String s2("Tom");
// 调用拷贝构造函数
String s3 = s2;
// 调用重载的等号运算符函数, 右操作数是 String 对象
s1 = s2;
// 调用重载的等号运算符函数, 右操作数是 字符串常量值 , char* 指针类型
s3 = "Jerry";
// 调用重载的下标运算符函数
char c = s3[3];
// 调用 重载的 左移运算符 函数
cout << s3 << endl;
// 控制台暂停 , 按任意键继续向后执行
system("pause");
return 0;
}