class string

class String from C++_OOP_base1_houjie

string.h

#ifndef __MYSTRING__
#define __MYSTRING__

using namespace std;

class String
{
public:
    String (const char*); // const: 不修改该指针; 函数会修改目的端对象的成员变量,所以
    // *Big Three*
    // **class with pointer members必须有copy ctor(1)和copy op=(2)**; 
    // **default copy op=会将对象a的数据(pointer) copy到对象b中(pointer),即将b的指针指向a所指的字符数组; 然而我们希望赋值之后两个字符数组的内容相同,而现在只有**
    // 1. 拷贝构造(copy constructor): 接受的是自己这种东西
    String (const String& str); // 注意默认参数不能同时出现在声明和定义中
    // 2. 拷贝赋值(copy assignment operator): 接受的是自己这种东西
    String& operator= (const String& str); 
    // 3. 析构函数(destructor):String对象死亡时会自动调用析构
    ~String();
    char* get_c_str() const { return m_data; } // get c-like string; default inline
private:
    char* m_data; // 放一个指针指向不固定大小的字符数组; 而非直接使用字符数组;
    // 对象内只有这个指针,字符数组不属于对象内,是被动态分配到其他地方的;
};

// String::function(...)...
#include <string.h>
inline String::String (const char* cstr = 0)
{
    if (cstr) { // class有pointer member时多半需要动态内存分配
        m_data = new char[strlen(cstr) + 1]; // return the addr of char array; strlen ignore '\0';
        strcpy(m_data, cstr);
    } else { // 空指针的时候分配一个'/0'即可
        m_data = new char[1]; // char array
        *m_data = '\0';
    }
}

inline String::~String()
{
    // 如果动态内存分配了,就需要在对象死亡之前调用析构函数的时候释放掉内存;
    delete[] m_data; // clean up memory to avoid leaks
}

inline String::String (const String& str)
{
    m_data = new char[strlen(str.m_data + 1)]; 
    strcpy(m_data, str.m_data);
}

inline String& String::operator= (const String& str) // 注意这里的&是reference,要放在typename的后面;
{
    // **一定要在拷贝赋值函数中检测是否自我赋值(self assignment)**
    // 自我赋值的时候两个指针指向同一块字符数组,delete[]之后就寄了;
    if (this == &str) // 注意这里的&是取地址 address of,要放在object的前面; 得到一个指针;
        return *this;

    // 清空左值-创建空间-复制右值
    delete[] m_data;
    m_data = new char[strlen(str.m_data) + 1];
    strcpy(m_data, str.m_data);

    return *this; // 允许连续赋值
    // 直接传value出去,不用管接收方使用value还是引用
}

// Global-function(...)...
#include <iostream>
// << 要使用非成员函数,无法直接访问m_data;
ostream& operator<< (ostream& os, const String& str)
{
    os << str.get_c_str(); // 内置的cout可以根据指针输出字符串
    return os;
}

#endif

string-test.cpp

#include <iostream>
#include "string.h"
using namespace std;

int main()
{
    String s1; // 不能写作String s1(); 这是一个function
    String s2("hello");

    String* p = new String("hello"); // p是一个新指针,指向字符数组的那个指针(该指针指向另一个指针)
    delete p; // 这三个都会调用析构函数释放字符串的指针,而这个指针需要额外释放指针的指针;

    String s3(s1); // 拷贝构造
    // 等价于String s3 = s1; 把s1赋值到s3, 且s3是新创建的,所以调用拷贝构造;
    cout << s3 << endl;
    s3 = s2; // 拷贝赋值
    cout << s3 << endl;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值