赞
踩
使用 成员函数 实现 等于判断 == 运算符重载 :
operate>
;operate>
operator>(String& s)
bool operator>(String& s)
// 重载 大于 > 运算符
bool String::operator>(String& s)
{
// 将 String 类比较转为 字符串比较
// 大于 和 小于 区别是 参数顺序不同的区别
return strcmp(this->m_p, s.m_p);
}
使用 成员函数 实现 小于 < 运算符重载 :
operate<
;operate<
operator<(String& s)
bool operator<(String& s)
// 重载 小于 < 运算符
bool String::operator<(String& s)
{
// 将 String 类比较转为 字符串比较
// 大于 和 小于 区别是 参数顺序不同的区别
return strcmp(s.m_p, this->m_p);
}
左移 << 操作符 cout << s << endl , 是将 s 对象输出到 cout 标准输出流中 ;
右移 >> 操作符 cin << s , 是将 标准输入流 cin 中的内容输入到 s 对象中 ;
使用 成员函数 实现 右移 >> 运算符 重载 :
operate>>
;operate>>
operator>>(String& s)
istream& operator>>(String& s)
// 全局函数 中实现 String 右移运算符重载
// 返回 istream& 引用类型 , 是为了支持链式调用 cin >> s1 >> endl;
istream& operator>>(istream& in, String& s)
{
cin >> s.m_p;
return in;
}
在 String 内部类中 , 将 上述 全局函数 声明为 String 的 友元函数 ;
// 使用 全局函数 实现 右移运算符 >> 重载
// 将全局函数 声明为 String 的友元函数
friend istream& operator>>(istream& in, String& s);
#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); // 重载 大于 > 运算符 bool operator>(String& s); // 重载 小于 < 运算符 bool operator<(String& s); // 使用 全局函数 实现 左移运算符 << 重载 // 将全局函数 声明为 String 的友元函数 friend ostream& operator<<(ostream& out, String& s); // 使用 全局函数 实现 右移运算符 >> 重载 // 将全局函数 声明为 String 的友元函数 friend istream& operator>>(istream& in, 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; } // 重载 大于 > 运算符 bool String::operator>(String& s) { // 将 String 类比较转为 字符串比较 // 大于 和 小于 区别是 参数顺序不同的区别 return strcmp(this->m_p, s.m_p); } // 重载 小于 < 运算符 bool String::operator<(String& s) { // 将 String 类比较转为 字符串比较 // 大于 和 小于 区别是 参数顺序不同的区别 return strcmp(s.m_p, this->m_p); } // 获取私有成员 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; } // 全局函数 中实现 String 右移运算符重载 // 返回 istream& 引用类型 , 是为了支持链式调用 cin >> s1 >> endl; istream& operator>>(istream& in, String& s) { cin >> s.m_p; return in; }
#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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。