[c++] 自写 MyString 类

实现了 MyString 类,同时实现了运算符重载,重载的运算符包括 <、>、==、!=、<<、>>、[] 等。

如果一个类重载了某个运算符,那么对这个类的对象进行操作的时候便会使用类重载的运算符。比如下边代码 MyString 类中重载了 <、>、==、!=、<<、>> 运算符,那么使用这些运算符操作对象的时候,便会使用对象重载之后的运算符。

(1) <、>、==、!=

① 4 个运算符重载,可以声明为友元函数,也可以声明为类的成员函数

② 声明友元函数时,形参是两个;声明为成员函数时,形参是一个

③ 对象 O1 和 O2 进行比较,成员函数是 O1.operator < (O1);友元函数是 operator < (O1, O2)

④ 声明为成员函数时,默认会带一个 this 指针,*this 是左操作数

(2) <<,>> 流操作符,需要声明为友元函数,不能声明为成员函数

(3) 不能创建新的运算符,只能重载已有的运算符

如下代码,<、>、==、!=、<<、>> 均声明为友元函数。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>

class MyString {
public:
  MyString(); // 默认构造函数
  MyString(int n, char c); // 普通构造函数
  MyString(const char *str); // 普通构造函数
  MyString(const MyString &str); // 拷贝构造函数

  MyString& operator = (char *str); // 重载 =,使用字符串赋值
  MyString& operator = (const MyString &s); // 重载 =,使用对象赋值

  ~MyString(); // 析构函数

  char& operator[] (int i); // 重载 [], 实现数组操作
  const char& operator[] (int i) const; // 重载 [],事项数组操作,对象为常量

  MyString& operator += (const MyString& str); // 重载 +=,与对象相加
  MyString& operator += (const char *str); // 重载 +=,与字符串相加

  friend std::ostream& operator << (std::ostream& out, MyString& str); // 重载 <<,实现输出流
  friend std::istream& operator >> (std::istream& in, MyString& str); // 重载 >>,实现输入流

  friend bool operator < (const MyString& left, const MyString& right); // 重载 <
  friend bool operator > (const MyString& left, const MyString& right); // 重载 >
  friend bool operator == (const MyString& left, const MyString& right); // 重载 ==
  friend bool operator != (const MyString& left, const MyString& right); // 重载 !=

  char *GetData() const;

  // 对象被声明为 const,那么这个对象调用的函数也需要是 const 类型
  int Size() const;

private:
  int size;
  char *data = nullptr;
};

MyString::MyString() {
  // 默认构造函数,只包括一个字符 '\0'
  printf("MyString()\n");
  data = new char[1];
  *data = '\0';
  size = 0;
}

MyString::MyString(int n, char c) {
  printf("MyString(int n, char c), n = %d, c = %c\n", n, c);
  data = new char[n + 1];
  for (int i = 0; i < n; i++) {
    *(data + i) = c;
  }
  *(data + n) = '\0';
  size = n;
}

MyString::MyString(const char *str) {
  printf("MyString(const char *str), str = %s\n", str);
  if (str == nullptr) {
    data = new char[1];
    *data = '\0';
    size = 0;
  } else {
    data = new char[strlen(str) + 1];
    strcpy(data, str);
    size = strlen(str);
  }
}

MyString::MyString(const MyString &str) {
  printf("MyString(const MyString &str), str = %s\n",  str.GetData());
  data = new char[str.size + 1];
  strcpy(data, str.data);
  size = str.size;
}

MyString& MyString::operator = (char *str) {
  printf("operator =, MyString = char *, str = %s\n", str);
  if (data != nullptr) {
    delete []data;
  }
  data = new char[strlen(str) +1];
  strcpy(data, str);
  return *this;
}

MyString&MyString::operator = (const MyString& str) {
  printf("operator =, MyString = MyString, str = %s\n", str.GetData());
  if (this == &str) {
    return *this;
  }

  if (data != nullptr) {
    delete []data;
  }

  data = new char[str.size + 1];
  strcpy(data, str.data);
  return *this;
}

MyString::~MyString() {
  if (data != nullptr) {
    delete []data;
    data = nullptr;
    size = 0;
  }
}

char& MyString::operator [](int i) {
  return data[i];
}

const char& MyString::operator[] (int i) const {
  printf("operator [], const\n");
  return data[i];
}

MyString& MyString::operator +=(const MyString& s) {
  printf("operator += MyString, str = %s\n", s.GetData());
  int length = size + s.size + 1;
  char *tmp = data;
  data = new char[length];
  size = length - 1;
  strcpy(data, tmp);
  strcat(data, s.data);
  delete []tmp;
  return *this;
}

MyString& MyString::operator += (const char *str) {
  printf("operator += char *, str = %s\n", str);
  if (str == nullptr) {
    return *this;
  }

  int length = size + strlen(str) + 1;
  char *tmp = data;
  data = new char[length];
  size = length - 1;
  strcpy(data, tmp);
  strcat(data, str);
  delete []tmp;
  return *this;
}

int MyString::Size() const {
  return size;
}

char* MyString::GetData() const {
  return data;
}

std::ostream& operator << (std::ostream &out, MyString &str) {
  for (int i = 0; i < str.Size(); i++) {
    out << str[i] << " ";
  }
  return out;
}

std::istream& operator >> (std::istream& in, MyString& str) {
  char p[50];
  in.getline(p, 50);
  str = p;
  return in;
}

bool operator < (const MyString& left, const MyString& right) {
  int i = 0;
  while (left[i] != '\0' && right[i] != '\0' && left[i] == right[i]) {
    i++;
  }

  if (left[i] < right[i]) {
    return true;
  }
  return false;
}

bool operator > (const MyString& left, const MyString& right) {
  int i = 0;
  while (left[i] != '\0' && right[i] != '\0' && left[i] == right[i]) {
    i++;
  }

  if (left[i] > right[i]) {
    return true;
  }
  return false;
}

bool operator == (const MyString& left, const MyString& right) {
  if (left.Size() != right.Size()) {
    return false;
  }

  int i = 0;
  while (left[i] != '\0' && right[i] != '\0') {
    if (left[i] != right[i]) {
      return false;
    }
    i++;
  }

  return true;
}

bool operator != (const MyString& left, const MyString& right) {
  if (left.Size() != right.Size()) {
    return true;
  }

  int i = 0;
  while (left[i] != '\0' && right[i] != '\0') {
    if (left[i] != right[i]) {
      return true;
    }
    i++;
  }

  return false;
}

int main() {
  printf("构造 --------------------------------\n");
  MyString s1(3, 'a'); // 默认构造函数
  MyString s2(s1); // 拷贝构造函数
  MyString s3("abcdefghijklmn"); // 通过 char * 来构造函数
  MyString s4; // 空的字符串

  printf("\noperator << --------------------------------\n");
  std::cout << "s1: " << s1 << std::endl; // 输出字符串,使用重载的运算符 <<
  std::cout << "s2: " << s2 << std::endl;
  std::cout << "s3: " << s3 << std::endl;
  std::cout << "s4: " << s4 << std::endl;

  printf("\noperator = --------------------------------\n");
  s4 = s3; // 字符串赋值,使用字符串对象赋值
  std::cout << "s4: " << s4 << std::endl;
  s4 = "abcd"; // 使用 char * 赋值
  std::cout << "s4: " << s4 << std::endl;

  std::cout << "s4[2] = " << s4[2] << std::endl;

  printf("\noperator += --------------------------------\n");
  s4 += "mmmm";
  std::cout << "s4: " << s4 << std::endl;
  s4 += s2;
  std::cout << "s4: " << s4 << std::endl;

  printf("\noperator >> --------------------------------\n");
  std::cin >> s2;
  std::cout << "s2: " << s2 << std::endl;

  printf("\n<, >, ==, != --------------------------------\n");
  MyString t1 = "1234";
  MyString t2 = "1234";

  MyString t3 = "12345";
  MyString t4 = "12335";
  std::cout << "t1 == t2 ? " << (t1 == t2) << std::endl;
  std::cout << "t1 < t3 ? " << (t1 < t3) << std::endl;
  std::cout << "t1 > t4 ?  " << (t1 > t4) << std::endl;
  std::cout << "t1 != t4 ? " << (t1 != t4) << std::endl;
  return 0;
}

如下代码,<、>、==、!= 声明为成员函数,当成员函数和友元函数同时存在时,优先选用成员函数。

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <string>

class MyString {
public:
  MyString(); // 默认构造函数
  MyString(int n, char c); // 普通构造函数
  MyString(const char *str); // 普通构造函数
  MyString(const MyString &str); // 拷贝构造函数

  MyString& operator = (char *str); // 重载 =,使用字符串赋值
  MyString& operator = (const MyString &s); // 重载 =,使用对象赋值

  ~MyString(); // 析构函数

  char& operator[] (int i); // 重载 [], 实现数组操作
  const char& operator[] (int i) const; // 重载 [],事项数组操作,对象为常量

  MyString& operator += (const MyString& str); // 重载 +=,与对象相加
  MyString& operator += (const char *str); // 重载 +=,与字符串相加

  friend std::ostream& operator << (std::ostream& out, MyString& str); // 重载 <<,实现输出流
  friend std::istream& operator >> (std::istream& in, MyString& str); // 重载 >>,实现输入流

  friend bool operator < (const MyString& left, const MyString& right); // 重载 <
  friend bool operator > (const MyString& left, const MyString& right); // 重载 >
  friend bool operator == (const MyString& left, const MyString& right); // 重载 ==
  friend bool operator != (const MyString& left, const MyString& right); // 重载 !=

  bool operator < (const MyString& str); // 重载 <
  bool operator > (const MyString& str); // 重载 >
  bool operator == (const MyString& str); // 重载 ==
  bool operator != (const MyString& str); // 重载 !=

  char *GetData() const;

  // 对象被声明为 const,那么这个对象调用的函数也需要是 const 类型
  int Size() const;

private:
  int size;
  char *data = nullptr;
};

MyString::MyString() {
  // 默认构造函数,只包括一个字符 '\0'
  printf("MyString()\n");
  data = new char[1];
  *data = '\0';
  size = 0;
}

MyString::MyString(int n, char c) {
  printf("MyString(int n, char c), n = %d, c = %c\n", n, c);
  data = new char[n + 1];
  for (int i = 0; i < n; i++) {
    *(data + i) = c;
  }
  *(data + n) = '\0';
  size = n;
}

MyString::MyString(const char *str) {
  printf("MyString(const char *str), str = %s\n", str);
  if (str == nullptr) {
    data = new char[1];
    *data = '\0';
    size = 0;
  } else {
    data = new char[strlen(str) + 1];
    strcpy(data, str);
    size = strlen(str);
  }
}

MyString::MyString(const MyString &str) {
  printf("MyString(const MyString &str), str = %s\n",  str.GetData());
  data = new char[str.size + 1];
  strcpy(data, str.data);
  size = str.size;
}

MyString& MyString::operator = (char *str) {
  printf("operator =, MyString = char *, str = %s\n", str);
  if (data != nullptr) {
    delete []data;
  }
  data = new char[strlen(str) +1];
  strcpy(data, str);
  return *this;
}

MyString&MyString::operator = (const MyString& str) {
  printf("operator =, MyString = MyString, str = %s\n", str.GetData());
  if (this == &str) {
    return *this;
  }

  if (data != nullptr) {
    delete []data;
  }

  data = new char[str.size + 1];
  strcpy(data, str.data);
  return *this;
}

MyString::~MyString() {
  if (data != nullptr) {
    delete []data;
    data = nullptr;
    size = 0;
  }
}

char& MyString::operator [](int i) {
  return data[i];
}

const char& MyString::operator[] (int i) const {
  return data[i];
}

MyString& MyString::operator +=(const MyString& s) {
  printf("operator += MyString, str = %s\n", s.GetData());
  int length = size + s.size + 1;
  char *tmp = data;
  data = new char[length];
  size = length - 1;
  strcpy(data, tmp);
  strcat(data, s.data);
  delete []tmp;
  return *this;
}

MyString& MyString::operator += (const char *str) {
  printf("operator += char *, str = %s\n", str);
  if (str == nullptr) {
    return *this;
  }

  int length = size + strlen(str) + 1;
  char *tmp = data;
  data = new char[length];
  size = length - 1;
  strcpy(data, tmp);
  strcat(data, str);
  delete []tmp;
  return *this;
}

int MyString::Size() const {
  return size;
}

char* MyString::GetData() const {
  return data;
}

std::ostream& operator << (std::ostream &out, MyString &str) {
  for (int i = 0; i < str.Size(); i++) {
    out << str[i] << " ";
  }
  return out;
}

std::istream& operator >> (std::istream& in, MyString& str) {
  char p[50];
  in.getline(p, 50);
  str = p;
  return in;
}

bool operator < (const MyString& left, const MyString& right) {
  int i = 0;
  while (left[i] != '\0' && right[i] != '\0' && left[i] == right[i]) {
    i++;
  }

  if (left[i] < right[i]) {
    return true;
  }
  return false;
}

bool operator > (const MyString& left, const MyString& right) {
  int i = 0;
  while (left[i] != '\0' && right[i] != '\0' && left[i] == right[i]) {
    i++;
  }

  if (left[i] > right[i]) {
    return true;
  }
  return false;
}

bool operator == (const MyString& left, const MyString& right) {
  if (left.Size() != right.Size()) {
    return false;
  }

  int i = 0;
  while (left[i] != '\0' && right[i] != '\0') {
    if (left[i] != right[i]) {
      return false;
    }
    i++;
  }

  return true;
}

bool operator != (const MyString& left, const MyString& right) {
  if (left.Size() != right.Size()) {
    return true;
  }

  int i = 0;
  while (left[i] != '\0' && right[i] != '\0') {
    if (left[i] != right[i]) {
      return true;
    }
    i++;
  }

  return false;
}

//
bool MyString::operator < (const MyString& str) {
  int i = 0;
  while (data[i] != '\0' && str[i] != '\0' && data[i] == str[i]) {
    i++;
  }

  if (data[i] < str[i]) {
    return true;
  }
  return false;
}

bool MyString::operator > (const MyString& str) {
  int i = 0;
  while (data[i] != '\0' && str[i] != '\0' && data[i] == str[i]) {
    i++;
  }

  if (data[i] > str[i]) {
    return true;
  }
  return false;
}

bool MyString::operator == (const MyString& str) {
  if (size != str.Size()) {
    return false;
  }

  int i = 0;
  while (data[i] != '\0' && str[i] != '\0') {
    if (data[i] != str[i]) {
      return false;
    }
    i++;
  }

  return true;
}

bool MyString::operator != (const MyString& str) {
  if (size != str.Size()) {
    return true;
  }

  int i = 0;
  while (data[i] != '\0' && str[i] != '\0') {
    if (data[i] != str[i]) {
      return true;
    }
    i++;
  }

  return false;
}

int main() {
  printf("构造 --------------------------------\n");
  MyString s1(3, 'a'); // 默认构造函数
  MyString s2(s1); // 拷贝构造函数
  MyString s3("abcdefghijklmn"); // 通过 char * 来构造函数
  MyString s4; // 空的字符串

  printf("\noperator << --------------------------------\n");
  std::cout << "s1: " << s1 << std::endl; // 输出字符串,使用重载的运算符 <<
  std::cout << "s2: " << s2 << std::endl;
  std::cout << "s3: " << s3 << std::endl;
  std::cout << "s4: " << s4 << std::endl;

  printf("\noperator = --------------------------------\n");
  s4 = s3; // 字符串赋值,使用字符串对象赋值
  std::cout << "s4: " << s4 << std::endl;
  s4 = "abcd"; // 使用 char * 赋值
  std::cout << "s4: " << s4 << std::endl;

  std::cout << "s4[2] = " << s4[2] << std::endl;

  printf("\noperator += --------------------------------\n");
  s4 += "mmmm";
  std::cout << "s4: " << s4 << std::endl;
  s4 += s2;
  std::cout << "s4: " << s4 << std::endl;

  printf("\noperator >> --------------------------------\n");
  std::cin >> s2;
  std::cout << "s2: " << s2 << std::endl;

  printf("\n<, >, ==, != --------------------------------\n");
  MyString t1 = "1234";
  MyString t2 = "1234";

  MyString t3 = "12345";
  MyString t4 = "12335";
  std::cout << "t1 == t2 ? " << (t1 == t2) << std::endl;
  std::cout << "t1 < t3 ? " << (t1 < t3) << std::endl;
  std::cout << "t1 > t4 ?  " << (t1 > t4) << std::endl;
  std::cout << "t1 != t4 ? " << (t1 != t4) << std::endl;
  return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/493493.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Java程序设计】【C00392】基于(JavaWeb)Springboot的校园生活服务平台(有论文)

基于&#xff08;JavaWeb&#xff09;Springboot的校园生活服务平台&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过…

如何压缩视频大小?3个很简单的方法~

有时候在网站上传视频时&#xff0c;最大限制上传大小为10M&#xff0c;可我要上传的视频体积有30M&#xff0c;这可怎么办呢&#xff1f;想必大家都遇到过类似的情景&#xff0c;或是为了节约磁盘、网盘的空间&#xff0c;方便文件传输发送等&#xff0c;如何压缩视频大小&…

LeetCode讲解算法2-数据结构[栈和队列](Python版)

文章目录 一、栈1.1 栈的定义1.2 栈的实现分析步骤1.3 栈的应用匹配圆括号匹配符号模2除法&#xff08;十进制转二进制&#xff09;进制转换 二、队列2.1 单向队列2.2 双端队列2.3 队列的应用验证回文串滑动窗口最大值 一、栈 1.1 栈的定义 栈是一种线性数据结构&#xff0c;栈…

maya导入导出bvh 自动 脚本

目录 maya打开脚本编辑器 运行打开bvh脚本 maya导出bvh脚本 maya打开脚本编辑器 打开Maya软件,点击右下角 “脚本编辑器” 运行打开bvh脚本<

一本书掌握数字化运维方法,构建数字化运维体系

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是尘缘&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f449;点击这里&#xff0c;就可以查看我的主页啦&#xff01;&#x1f447;&#x…

【计算机考研】408到底有多难?

你真以为大家是学不会408吗&#xff1f; 不是&#xff01;单纯是因为时间不够&#xff01;&#xff01;&#xff01; 再准确一些就是不会分配时间 408的知识其实并不难&#xff0c;要说想上130那确实有难度&#xff0c;但是100在时间充裕的情况下还是可以做到的 我本人是双…

程序员如何兼职赚小钱?

程序员由于有技术和手艺其实兼职赚钱的路子还是挺多的&#xff0c;只要你有足够的时间。 1. 做外包 这是比较传统的方式&#xff0c;甲方在一些众包平台上发布开发任务&#xff0c;你可以抢这个任务&#xff0c;但是价格都比较便宜。 任务比较多的平台: 猪八戒、一品威客、开…

第5章 数据建模和设计

思维导图 5.1 引言 最常见的6种模式&#xff1a;关系模式、多维模式、面向对象模式、 事实模式、时间序列模式和NoSQL模式 每种模式分为三层模型&#xff1a;概念模型、逻辑模型和物理模型 每种模型都包含一系列组件&#xff1a;如实体、关系、事实、键和属性。 5.1.1 业务驱…

单页面应用部署到iis上可以正常打开,刷新就404

当您遇到Dumi打包的网站部署到IIS上可以正常打开首页,但刷新页面时出现404错误的情况,这通常与以下几个方面有关: 路由处理: Dumi生成的项目通常基于SPA(Single Page Application)架构,使用前端路由来实现无刷新导航。这意味着大部分页面切换是在浏览器层面完成的,而不…

嵌入式学习46——硬件相关2串口通信

串口&#xff1a; 端口&#xff1a; COM 波特率&#xff1a; 9600 115200 &#xff08;bps&#xff09; 每秒传输的数据…

35.HarmonyOS App(ArkUI)使用父组件@Builder装饰的方法初始化子组件@BuilderParam报错

HarmonyOS App(ArkUI)使用父组件Builder装饰的方法初始化子组件BuilderParam报错 Type void is not assignable to type () > void. <tsCheck> 去掉括号()就可以了 装饰器&#xff1a; 用于装饰类、结构、方法以及变量&#xff0c;并赋予其特殊的含义。如上述示例中En…

使用LangChain、LangGraph和LangSmith来创建AI Agent

LangGraph LangGraph是建立在LangChain之上的一个框架&#xff0c;它使得创建和管理智能体&#xff08;Agent&#xff09;及其运行时环境变得更加简单。 在LangChain的架构中&#xff0c;智能体是指由语言模型控制的系统&#xff0c;它能够自主决策接下来要执行的操作。而智能…

js算法记录

> 更多请前往 https://www.passerma.com/article/86 滑动窗口 1 给定一个矩阵&#xff0c;包含N*M个整数&#xff0c;和一个包含K个整数的数组。现在要求在这个矩阵中找一个宽度最小的子矩阵&#xff0c;要求子矩阵包含数组中所有的整数 function minSubmatrixWidth(mat…

【Redis教程0x07】Redis持久化之AOF日志

引言 在【Redis教程0x06】中我们说到过&#xff0c;Redis的持久化有3种策略&#xff1a;RDB快照、AOF日志、RDB和AOF混合持久化。 本篇博客我们就将介绍一下AOF日志是怎么回事&#xff0c;以及混合持久化是怎么实现的。 AOF持久化 AOF日志 AOF是Append Only File的缩写&…

c语言知识点整理------基础c语言框架,数据类型,变量常量,注释

前言 本文不涉及讲解原理&#xff0c;用简洁明了的风格&#xff0c;去整理方便查阅的知识点。 &#xff08;适合有编程基础&#xff0c;或者需要作为笔记的人群使用&#xff09; 程序基本框架 结果会输出hello world。 程序的执行 c语言属于编译型语言。 代码执行分为五个…

阿里云服务器租用价格表-2024最新(附明细报价)

2024年阿里云服务器优惠价格表&#xff0c;一张表整理阿里云服务器最新报价&#xff0c;阿里云服务器网aliyunfuwuqi.com整理云服务器ECS和轻量应用服务器详细CPU内存、公网带宽和系统盘详细配置报价单&#xff0c;大家也可以直接移步到阿里云CLUB中心查看 aliyun.club 当前最新…

如何在家中使用手机平板电脑 公司iStoreOS软路由实现远程桌面

文章目录 简介一、配置远程桌面公网地址二、家中使用永久固定地址 访问公司电脑**具体操作方法是&#xff1a;** 简介 软路由是PC的硬件加上路由系统来实现路由器的功能&#xff0c;也可以说是使用软件达成路由功能的路由器。 使用软路由控制局域网内计算机的好处&#xff1a…

el-select动态禁用

在一个el-form表单中有5个el-form-item; 每个el-form-item是一个el-select控件&#xff1b; 这5个el-select控件遵循这样的规则&#xff0c;都是使用同一个list集合&#xff0c;如果第一个el-select选择了list中的某一项&#xff0c;那么这一项就被禁用&#xff1b;其他的el-…

数据库-索引快速学

索引 当表中数据量庞大时&#xff0c;往往搜索一条数据就会耗费很长的时间等待 索引是帮助数据库高效获取数据的数据结构 create index 索引名 on 数据表名&#xff08;字段名&#xff09;;为该表下的某一字段创建索引&#xff0c;检索耗时会大大的减小 索引的优缺点 优点&…

linux下关闭swap文件系统

临时关闭&#xff08;马上生效&#xff09; 永久关闭&#xff08;重启计算机才能生效&#xff09; vim /etc/fstab