用C++实现简单的字符串值类型对象

问题:
值类型在c++中是一个很重要的概念,指的是一个类的实例像int类型一样,可以被复制、构造、传递,而且不需要用户去担心(至少在表面上)new和delete的问题。
那么构造一个完整的值类型需要注意哪些方面呢?

让我们一字符串类型来做一个简单的设计。

首先我们要明确这个类型的实例可以有哪些操作,我们就要通过构造函数和重载函数实现这些操作。

#include<iostream>
#include<cmath>
#include<iomanip>
#include<vector>
using namespace std;

struct String
{
public:
    String();
    String(const char *);
    String(const String &);
    String(String &&);
    ~String();

    String & operator=(const String &);
    String & operator=(String &&);

    bool operator==(const String &) const;
    bool operator!=(const String &) const;
    bool operator<(const String &) const;
    bool operator<=(const String &) const;
    bool operator>(const String &) const;
    bool operator>=(const String &) const;

    const char *GetBuffer() const;
    size_t GetLength() const;
    String operator+(const String &) const;
    String SubString(int start, int length) const;


};

下边是一个简单的字符串值类型实现;

在写这种代码的时候,最好用到单元测试(更大的叫TDD(测试驱动开发,用测试来驱动软件的开发))
参考书籍
用这种方法的作用:
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <cstdlib>
#include <cstring>
#ifndef _MSC_VER
#define strcpy_s(DST,SIZE,SRC) strcpy((DST),(SRC))
#endif

#define JSK_ASSERT(EXPRESSION) if(!(EXPRESSION)) throw 0
using namespace std;

struct String
{
private:
    size_t length;
    char* buffer;

public:
    String():length{0},buffer{new char[1]{'\0'}}
    {
    }

    String(const char* theBuffer):length{strlen(theBuffer)},buffer{new char[length+1]}
    {
        strcpy_s(buffer,length+1,theBuffer);
        cout << " =";
    }

     String(const String& theString):length{theString.length},buffer{new char[theString.length+1]}
    {
        strcpy_s(buffer,length+1,theString.buffer);
    }
    String(String&& theString)
        :length{ theString.length }
        , buffer{ theString.buffer }
    {
		theString.buffer = nullptr;
    }
    ~String()
    {
        delete[] buffer;
    }

     String& operator=(const String& theString)
    {
        if (this != &theString)
        {
            delete[] buffer;
            length = theString.length;
            buffer = new char[length+1];
            strcpy_s(buffer,length+1,theString.buffer);
        }
        return *this;//这里返回的类型是左值引用类型,并不会在返回时创建零时对象,而且this相对于这个重载函数是一直存在的并不是函数里的局部变量,所以可以返回左值引用类型
    }
    String& operator=(String&& theString)
    {
        if (this != &theString)
        {
            delete[] buffer;
            length = theString.length;
            buffer = theString.buffer;
            theString.buffer = nullptr;
        }
        return *this;
    }


    const char* GetBuffer()const
    {
        return buffer;
    }

    size_t GetLength()const
    {
        return length;
    }
};

int main()
{
    {
        String s;//调用String()默认构造函数
        JSK_ASSERT(s.GetBuffer() != nullptr);
        JSK_ASSERT(s.GetBuffer()[0] == '\0');
        JSK_ASSERT(s.GetLength() == 0);
    }
    {
        String s = "This is a string!";//调用 String(const char* theBuffer)初始化(非缺省)构造函数
        JSK_ASSERT(s.GetBuffer() != nullptr);
        JSK_ASSERT(strcmp(s.GetBuffer(), "This is a string!") == 0);
        JSK_ASSERT(s.GetBuffer()[17] == '\0');
        JSK_ASSERT(s.GetLength() == 17);
    }
    {
        String s = "This is a string!";
        String t = s;//调用 String(const String& theString)复制构造函数
        JSK_ASSERT(t.GetBuffer() != nullptr);
        JSK_ASSERT(s.GetBuffer() != t.GetBuffer());
        JSK_ASSERT(s.GetLength() == t.GetLength());
        JSK_ASSERT(strcmp(s.GetBuffer(), t.GetBuffer()) == 0);
    }

    
    {
        String s = "This is a string!";
        s = s;//调用等号运算符重载函数String& operator=(const String& theString)
        JSK_ASSERT(s.GetBuffer() != nullptr);
        JSK_ASSERT(strcmp(s.GetBuffer(), "This is a string!") == 0);
        JSK_ASSERT(s.GetBuffer()[17] == '\0');
        JSK_ASSERT(s.GetLength() == 17);
    }
    {
        String s = "This is a string!";
        String t;
        t = s;//调用等号运算符重载函数String& operator=(const String& theString)
        JSK_ASSERT(t.GetBuffer() != nullptr);
        JSK_ASSERT(s.GetBuffer() != t.GetBuffer());
        JSK_ASSERT(s.GetLength() == t.GetLength());
        JSK_ASSERT(strcmp(s.GetBuffer(), t.GetBuffer()) == 0);
    }
	
	{
        String s = "This is a string!";
        String t = std::move(s);//调用String(String&& theString),转移复制构造函数(也即右值引用复制构造函数)
        JSK_ASSERT(s.GetBuffer() == nullptr);
        JSK_ASSERT(t.GetBuffer() != nullptr);
        JSK_ASSERT(t.GetLength() == 17);
        JSK_ASSERT(strcmp(t.GetBuffer(), "This is a string!") == 0);
    }
    {
        String s = "This is a string!";
        s = std::move(s);
        JSK_ASSERT(s.GetBuffer() != nullptr);
        JSK_ASSERT(strcmp(s.GetBuffer(), "This is a string!") == 0);
        JSK_ASSERT(s.GetBuffer()[17] == '\0');
        JSK_ASSERT(s.GetLength() == 17);
    }
    {
        String s = "This is a string!";
        String t;
        t = std::move(s);//调用转移操作符重载函数String& operator=(String&& theString)(也即右值引用操作符重载函数)
  
        JSK_ASSERT(s.GetBuffer() == nullptr);
        JSK_ASSERT(t.GetBuffer() != nullptr);
        JSK_ASSERT(t.GetLength() == 17);
        JSK_ASSERT(strcmp(t.GetBuffer(), "This is a string!") == 0);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值