string类的实现

前言:
String类的实现是C++学习者很基本的能力考察,今天自己也来尝试C++风格字符串操作String类的实现:

/*
* to be improved by my own strcpy, strlen, strcmp 
* 实现说明: 实现说明:字符串类String的简单实现,内部采用字符数组实现
* 经验说明:经验说明:拷贝构造函数、重载赋值运算符、实现析构函数三个操作在实现自定义类时往往同时出现。
* 参考资料: http://rsljdkt.iteye.com/blog/774188  ,  《剑指offer》
*/

#include<iostream>
#include<cstring>
#include<cassert>
#include<cstdlib> // exit()
using namespace std;

class String
{
public:
    String(const char *pstr = NULL);
    String(const String& other);
    ~String();
    String& operator=(const String& other);

    String operator+(const String& other);
    int size();
    String subStr(int start, int end);

    bool operator==(const String& other);
    friend ostream& operator<<(ostream& out, const String& other);

private:
    char *m_data;
};


String::String(const char *pstr) // 主要在定义是不要加上形参默认值
{
    if(pstr == NULL) 
    {
        m_data = new char[1];
        if(m_data == NULL)
            exit(-1);
        *m_data = '\0';
    }
    else
    {
        int len = strlen(pstr);
        m_data = new char[len+1];
        if(m_data == NULL)
            exit(-1);
        strcpy(m_data, pstr);   
    }
}

String::String(const String& other)
{
    int len = strlen(other.m_data);
    m_data = new char[len+1];
    if(m_data ==NULL)
        exit(-1);
    strcpy(m_data, other.m_data);
}

String::~String()
{
    if(NULL != m_data)
    {
        delete m_data;
        m_data = NULL;
    }
}

/* 
  在类的成员函数中,返回引用的类对象,当然不能是函数内定义的类对象(会释放掉),一般为this指向的对象;
  引用返回左值(即a=b=c是可以的),对于返回值的函数,其返回的是一个右值不可以改变的,
      因此返回的是值类型的话不可以连续赋值;
*/
String& String::operator=(const String& other)
{
    if(m_data != other.m_data)
    {
        String strTemp(other);
        char *pWant = strTemp.m_data;
        strTemp.m_data = m_data;
        m_data = pWant;
    }
    return *this;
}

// "+"运算符的重载不能返回引用,因为它返回的是在函数内定义的类对象;
String String::operator+(const String& other)
{
    String ret;
    delete[] ret.m_data; // 这就是前面为什么new char[1];的原因,同一delete[]来释放即可
    ret.m_data = new char[(strlen(m_data) + strlen(other.m_data) + 1)];
    if(m_data == NULL)
        exit(-1);
    strcpy(ret.m_data, m_data);
    strcpy(ret.m_data+strlen(m_data), other.m_data);
    return ret;
}

int String::size()
{
    return strlen(m_data);
}

String String::subStr(int start, int end)
{
    assert(start>=0 && end>=0);
    String ret;
    if(end > start)
    {
        delete[] ret.m_data;
        ret.m_data = new char[end - start+1];
        if(ret.m_data == NULL)
            exit(-1);
        for(int i=0; i+start < end; i++)
        {
            ret.m_data[i] = m_data[start+i];
        }
        ret.m_data[end-start] = '\0';
    }
    return ret;
}


bool String::operator==(const String& other)
{
    return strcmp(m_data, other.m_data) == 0;
}

ostream& operator<<(ostream& out, const String& other)
{
    out << other.m_data;
    return out;
}



void test()
{
    String s = "abcd";
    String t = "abcd";
    cout << s << (s==t ?" == ":" != ") << t << endl;

    String s2 = "Hello";
    String s3 = "China";
    cout << s2 + s3 << endl;
    cout << (s2+s3).subStr(0, s2.size() + s3.size()) << endl;
    cout << (s2+s3).subStr(4, 5) << endl;

    String s4;
    String s5;
    s4 = s5 = s2 = s;
    cout << "s4= " << s4 << endl;
    cout << "s5= " << s5 << endl;
    cout << "s2= " << s2 << endl;


}



int main()
{
    String s1 = "hello test";
    String s2 = s1; // 隐式调用拷贝构造函数
    String s3 = "hello test";
    String s4("stringDemo"); // 显式调用拷贝构造函数
    String s5(s4);
    String s6;
    String s7 =s6;
    cout << "s1= " << s1 << endl;
    cout << "s2= " << s2 << endl;
    cout << "s4= " << s4 << " s5= " << s5 << endl;
    cout << "s6= " << s6 << endl;
    cout << "s7= " << s7 << endl;
    cout << (s1 == s3) << endl;

    cout << "------------------------------\n";
    test();
    cout << "------------------------------" << endl;

    return 0;
}

思考:
1)String是不能被继承的,这里如果要改善可以考虑从这方面入手改进;
2)考虑为什么上面申请一个空间的时候不是new char, 而是new char[1];
3)考虑什么时候返回引用,什么时候返回对象而不是引用;
4)理解为什么参数中可以使用对象的私有成员,感受什么叫做私有成员内部可以被调用,外部不可以被调用;

注:本文代码已在g++环境测试通过, 并通过上面测试用例;

待改进的地方: 不要使用库函数实现String即实现自己my_strlen(), my_strcmp(), 后续博文继续改造;

如果对文章中的内容有疑问或文章出错欢迎讨论指正,相互进步,谢谢;

参考资料:
http://rsljdkt.iteye.com/blog/774188 ,
《剑指offer》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值