c++学习之mystring的简单封装

简介: c++学习之mystring的简单封装

我们经常利用string类实例化对象来对字符串进行各种操作,string类是一个实用的类,那么对于string类的一些基本操作是如何实现的呢?我们简单的实现一下mystring的封装。

首先我们给出类模板:

其中主要的操作有:1,构造函数的实现 2,运算符的重载 。

对于string类的基本实现,我们知道string类是对字符串的操作,因此私有变量是字符指针和字符串的大小这两个成员,用来表示字符。其次就是对于字符指针,在这里我们为字符指针是专门开辟一片空间用来存放字符串的。

class mystring
{
  friend::ostream& operator<<(ostream& out, mystring  a);
  friend::istream& operator>>(istream& in, mystring &a);
public:
  mystring();//默认构造
  mystring(char* arr);//有参构造
  mystring(const mystring& p);//拷贝构造
  ~mystring();
   int getsize()
     {
       return  size;
     }//获取大小
  //实现对字符串的访问,重载[]
   //这里将返回值进行引用,之后可以改变原本身的元素
   char &operator[](int index)
   {
     //判断位置是否合法
     if (index > 0 && index < size)
     {
       return arr[index];
     }
     else
     {
       cout << "下标越界" << endl;
       exit(-1);
     }
   }
//成员函数实现
   mystring operator+(mystring&a);
   mystring operator+ (char* str);
   mystring operator=(mystring a);
   mystring operator=(char* str);
   bool operator>(mystring a);
   bool operator<(mystring a);
   bool operator==(mystring a);
private:
  char* arr;
  int size;
};

其次对于成员函数我们在函数未定义,对于全局函数,例如输入输出我们需要设置为友元函数来实现对类中成员的访问。

1.常用的字符串函数

strcpy

常用的字符串拷贝函数,将右边的const char*的字符串赋值给左边的字符串。

0ada984a538b4e069cd169faa8b65593.png


strcat


4a91691a0a19410282fbe00d572433af.png

字符串追加函数,将右边的字符串追加给左边字符串的末尾,也就是连接两个字符串。


ea900c926f1e4eb78c67b3a9593121a9.png

将该字符串中的前多少元素初始化为什莫,比如我们将实现对申请的一片字符指针arr的空间初始化为0,memset(arr,0,strlen(arr)+1),将arr中的所有字符初始化为0.

2.构造函数的创建

1.无参构造

无参构造主要是将字符指针初始化为空,大小为零。

mystring::mystring()

{

   arr = NULL;

   size=0;

}

2.有参构造

有参构造传递字符串以实现初始化类中的字符指针,以及对大小的确定。

mystring::mystring( char* arr)
{
  this->arr = new char[strlen(arr)+1];//申请空间
  memset(this->arr, 0, strlen(arr)+1);//初始化全设置为0
  strcpy(this->arr, arr);//实现拷贝
  size = (int)strlen(arr) ;
}

注意这里是给指针专门开辟空间,所以对于指针在析构时,我们需要释放空间。

3.拷贝构造

拷贝原类改变为新类

mystring::mystring(const mystring& p)
{
  size = p.size;
  this->arr = new char[size+ 1];
  memset(arr, 0, strlen(p.arr) + 1);//初始化全设置为0
  strcpy(this->arr,p.arr);//实现拷贝
}

拷贝构造实现形式与构造函数的形式一样。

析构

mystring ::~mystring()
{
  if (arr != NULL)
  {
    delete[]arr;
    arr = NULL;
  }
}

因为是对指针开辟空间,对应要释放空间。

3.运算符的重载

1.重载输出运算符

//重载输出运算符(全局重载)
   ostream& operator<<( ostream&out,mystring  a)
  {
     out << a.arr ;
     return out;
  }

与之前学习到的重载输出运算符一样,返回类型为输出流,操作对象是mystring类。

注意对于输入与输出运算符的重载,我们都需要将返回值引用,实现对输入输出的所有操作。

2.重载输入运算符

重载输入运算符需要注意,原类中的字符指针是否为空,不为空要置空,然后再创建一个mystring作为媒介实现输入,之后再赋值,反回输入流。

//重载输入运算符
   istream& operator>>(istream&in, mystring &a)
   {
     char buffer[100];
     in >> buffer;
     //判断是否为空
     if (a.arr != NULL)
     {
       delete[]a.arr;
       a.arr = NULL;
     }
     a.size =(int)strlen(buffer);
     a.arr = new char[a.size+1];
     //置空
     memset(a.arr, 0, a.size + 1);//注意这里不能用strlen(a.arr),在这里是未知访问
     strcpy(a.arr, buffer);
     return in;
   }

3.重载+运算符

+运算符在string类中的操作是字符串的连接。

这里需要注意的是,我们是对字符串类的对象与字符串类+重载的实现,字符串类的对象与字符串+重载也是需要实现的,因为字符串类实例化的对象我们是将他当作字符串用的。

字符串类对象间的重载与字符指针的重载是类似的,主要是对其中的字符串的实现。

 //字符串与类对象+的重载
   mystring mystring::operator+(char* str)
   {
     mystring str1;
     str1.size = (int)strlen(str)+this->size;
     str1.arr = new char[str1.size + 1];
     memset(str1.arr, 0, str1.size);
     strcpy(str1.arr, this->arr);
     strcat(str1.arr, str);
     return str1;
   } 
  //重载加法运算符  类与类之间+重载
  mystring mystring:: operator+(mystring& a)
   {
     mystring str1;//作为媒介
     str1.size = this->size+a.size;
     str1.arr = new char[str1.size+1];
     memset(str1.arr, 0, str1.size);
     strcpy(str1.arr, this->arr);
     strcat(str1.arr, a.arr);
     return str1;
   }

两者的重载都是创建第三个类作为媒介,用来作为连接字符串后的字符串的载体,也是所返回的对象。因此在开辟空间的时候,需要注意空间的大小。

4.重载赋值运算符

string类中赋值运算符的作用就是字符串拷贝,但是是深度拷贝,所以我们需要开辟一片空间,对于类原this中所指向的空间实现地址的交换,即空间的交换。

还需要注意的是,这里的操作对象可以是类的对象值之间,也可以是类的对象直接与字符串直接的运算。

重载赋值运算符(只有指针成员时,需要深拷贝)
  mystring mystring:: operator=(mystring a)
  {
    //先判断是否为空
    if (this->arr != NULL)
    {
      delete[]arr;
      arr = NULL;
    }
    if (this->arr != NULL)
    {
      delete[]arr;
      arr = NULL;
    }
    //这里是深拷贝,即地址之间的交换
    this->size = a.size;
    this->arr = new char[a.size+1];
    memset(this->arr, 0, a.size);
    strcpy(this->arr, a.arr);
    return *this;
  }

这里在赋值时,我们还是需要判断一下这里的原this中的指针是否为空,不为空,我们要将它置空之后再进行拷贝。

mystring mystring::operator=(char* str)
  {
    if (this->arr != NULL)
    {
      delete[]arr;
      arr = NULL;
    }
    //这里是深拷贝,即空间之间的交换
    this->arr = new char[strlen(str)+1];
    memset(this->arr, 0, strlen(str));
    strcpy(this->arr, str);
    this->size = strlen(str);
    return *this;
  }

5.重载比较运算符

重载比较运算符是比较简单的,即>  < ==,显然他们的返回值都布尔型的。

重载>运算符

//重载>运算符
  bool mystring:: operator>(mystring a)
  {
    if (this->size > a.size)
    {
      return true;
    }
    else
    {
      return false;
    }
  }

重载<运算符

//重载<运算符
  bool mystring:: operator<(mystring a)
  {
    if (this->size < a.size)
    {
      return true;
    }
    else
    {
      return false;
    }
  }

重载==运算符

//重载==运算符
  bool mystring:: operator==(mystring a)
  {
    if (this->size == a.size)
    {
      return true;
    }
    else
    {
      return false;
    }
  }

如下是我所给出的操作用例,

int main()
{
  mystring str=(char *)"hello world";
  //mystring str ((char*)"hello world");
  cout << str << endl;
  mystring str1 = (char*)"haha";
  cout << str+str1 << endl;
  cout << str + (char *)"haha" << endl;
  str = str1;
  cout << str << endl;
  str = (char*)"heiehi";
  cout << str << endl;
  if (str >str1)
  {
    cout << "str大与str1" << endl;
  }
  else
  {
    cout << "str小与str1" << endl;
  }
}


cb16d68d4abf429ea5bb48387159e67e.png

好了,对于string的简单的实现就完成了,在此基础上我们还可以完成他的所有操作,在cplusplus上我们可以看到string所给出的定义string - C++ Reference (cplusplus.com)

STL中给出了string类的标准定义,以尽可能满足我们对字符串的某些操作,这些操作大家可以下去慢慢实现。


相关文章
|
2月前
|
算法 C语言 C++
C++语言学习指南:从新手到高手,一文带你领略系统编程的巅峰技艺!
【8月更文挑战第22天】C++由Bjarne Stroustrup于1985年创立,凭借卓越性能与灵活性,在系统编程、游戏开发等领域占据重要地位。它继承了C语言的高效性,并引入面向对象编程,使代码更模块化易管理。C++支持基本语法如变量声明与控制结构;通过`iostream`库实现输入输出;利用类与对象实现面向对象编程;提供模板增强代码复用性;具备异常处理机制确保程序健壮性;C++11引入现代化特性简化编程;标准模板库(STL)支持高效编程;多线程支持利用多核优势。虽然学习曲线陡峭,但掌握后可开启高性能编程大门。随着新标准如C++20的发展,C++持续演进,提供更多开发可能性。
49 0
|
1月前
|
数据安全/隐私保护 C语言 C++
C++(七)封装
本文档详细介绍了C++封装的概念及其应用。封装通过权限控制对外提供接口并隐藏内部数据,增强代码的安全性和可维护性。文档首先解释了`class`中的权限修饰符(`public`、`private`、`protected`)的作用,并通过示例展示了如何使用封装实现栈结构。接着介绍了构造器和析构器的使用方法,包括初始化列表的引入以及它们在内存管理和对象生命周期中的重要性。最后,通过分文件编程的方式展示了如何将类定义和实现分离,提高代码的模块化和复用性。
|
3月前
|
C++ 容器
【C++】map和set封装
【C++】map和set封装
31 2
|
3月前
|
存储 安全 编译器
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
【C++入门 四】学习C++内联函数 | auto关键字 | 基于范围的for循环(C++11) | 指针空值nullptr(C++11)
|
3月前
|
人工智能 分布式计算 Java
【C++入门 一 】学习C++背景、开启C++奇妙之旅
【C++入门 一 】学习C++背景、开启C++奇妙之旅
|
3月前
|
存储 自然语言处理 编译器
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
|
3月前
|
小程序 C++
【C++入门 二 】学习使用C++命名空间及其展开
【C++入门 二 】学习使用C++命名空间及其展开
|
3月前
|
存储 C++ 索引
|
3月前
|
存储 C++ 容器
|
3月前
|
算法 数据处理 C++
下一篇
无影云桌面