自实现 MyString 类

2023-10-20 16:52:39 浏览数 (2)

自实现 myString 类主要目的是剖析系统内部的 string 类的一些实现方法以及加强对类封装、运算符重载等特性的掌握。其中包含了几项非常重要的功能实现。

  1. 使用构造器创建对象。
  2. 拷贝构造器创建对象。
  3. 赋值运算符重载构造对象。
  4. []运算符重载构造对象数组。
  5. ==运算符重载判断对象是否相等。
  6. 运算符重载实现对象相加。
  7. >> << 流输入输出运算符实现打印和输入。

具体的实现代码分三个部分,一个 MyString.h 文件,包含类的声明和结构。一个 MyString.cpp 文件,包含类的成员及友元函数实现。最终是一个 main.cpp 来测试我们自己的 MyString 类是否可以正常使用。

【myString.h】

代码语言:javascript复制
#pragma once
#include <iostream>

class CMyString
{
public:
    // 构造器
    CMyString(char* str = NULL);
    // 拷贝构造器原型,another为传递进来的同类对象
    CMyString(const CMyString & another);
    // 赋值运算符重载,系统会提供默认,但同样是等位拷贝
    CMyString& operator=(const CMyString & another);
    // []运算符重载
    char operator[](int idx);
    // ==运算符重载
    bool operator==(const CMyString& another);
    //   运算符重载
    CMyString operator (const CMyString& another);
    // 流输入输出
    friend std::ostream& operator<<(std::ostream& os, CMyString& another);
    friend std::istream& operator<<(std::istream& is, CMyString& another);

    ~CMyString(void);
    char* c_str();
private:
    char* m_str;
};

【myString.cpp】

代码语言:javascript复制
#include "MyString.h"
#include <cstring>


CMyString::CMyString(char* str)
{
    if (str)
    {
        int len = strlen(str);
        m_str = new char[len   1];
        strcpy_s(m_str, len   1, str);
    }
    else
    {
        m_str = new char[1];
        *m_str = '';
    }
}

CMyString::CMyString(const CMyString & another)
{
    // 浅拷贝,等位拷贝,会造成 double free
    // 这样操作会导致 m_str 和 another.m_str 指向同一块堆内存
    // 析构时会造成 delete 了同一块内存
    // m_str = another.m_str;

    // 深拷贝,根据another.m_str的长度给对象new一块内存使双方不冲突
    int len = strlen(another.m_str);
    m_str = new char[len   1];
    strcpy_s(m_str, len   1, another.m_str);
}

CMyString& CMyString::operator=(const CMyString & another)
{
    if (this == &another)
    {
        // 解决 s6 = s6 会导致崩溃的问题
        return *this;
    }
    delete [] m_str;
    int len = strlen(another.m_str);
    m_str = new char[len   1];
    strcpy_s(m_str, len   1, another.m_str);
    return *this;
}

char CMyString::operator[](int idx)
{
    return m_str[idx];
}

bool CMyString::operator==(const CMyString& another)
{
    if (strcmp(this->m_str, another.m_str) == 0)
        return true;
    else
        return false;
}

CMyString CMyString::operator (const CMyString& another)
{
    int len = 0;
    len = strlen(this->m_str);
    len  = strlen(another.m_str);

    CMyString tmp;
    delete [] tmp.m_str;

    tmp.m_str = new char[len   1];
    memset(tmp.m_str, 0, len   1);
    strcat_s(tmp.m_str, len   1, this->m_str);
    strcat_s(tmp.m_str, len   1, another.m_str);

    return tmp;
}

std::ostream& operator<<(std::ostream& os, CMyString& another)
{
    os << another.m_str;
    return os;
}

std::istream& operator<<(std::istream& is, CMyString& another)
{
    // 先删除了原来保存的数据
    delete [] another.m_str;
    char buffer[BUFSIZ];
    is.getline(buffer, BUFSIZ);
    int length = strlen(buffer);
    another.m_str = new char[length   1];
    strcpy_s(another.m_str, length   1, buffer);
    return is;
}

CMyString::~CMyString(void)
{
    std::cout << "delete [] m_str : " << m_str << std::endl;
    delete [] m_str;
}

char* CMyString::c_str()
{
    return m_str;
}

【main.cpp】

代码语言:javascript复制
#include <iostream>
#include "MyString.h"

using namespace std;

int main(int argc, char* argv[])
{
    // 构造函数,无参数
    CMyString s;
    cout << s.c_str() << endl;

    // 构造函数,有参数
    CMyString s1("china");
    cout << s1.c_str() << endl;

    // 类型转化函数
    CMyString s2 = "china";
    cout << s2.c_str() << endl;

    /*
     以上均是调用构造器来创建的
     */

    // 拷贝构造器
    CMyString s3(s2);
    cout << s3.c_str() << endl;

    // 同上
    CMyString s4 = s3;
    cout << s4.c_str() << endl;

    // 赋值,=号运算符重载
    CMyString s5;
    // 等同于 s5.operator= (s4);
    s5 = s4;
    // 同上 相当于s5.operator=(s4.operator=(s3));
    s5 = s4 = s3;
    cout << s5.c_str() << endl;

    CMyString s6("china");
    // 这样操作会进入=号运算符重载的函数内
    // 但刚进入后 s6 就被 delete 了
    // 如果继续后面的操作将会导致访问违规内存而报错
    // 个别系统环境下可能不报错,带不代表就是正确的
    s6 = s6;
    cout << s6.c_str() << endl;

    // []运算符重载
    cout << s6[2] << endl;

    // ==运算符重载
    if (s5 == s6) cout << "s5 == s6" << endl;

    //   运算符重载
    CMyString s7 = s6   s5;
    cout << s7.c_str() << endl;

    cout << s7 << endl;

    getchar();
    return 0;
}

0 人点赞