c++--面向对象封装--实践

#include <iostream>
#include <cstring>
using namespace std;

class mystring {
private:
    char* buf;  // 指向存储字符串的堆空间
    int len;    // 记录字符串长度

public:
    // 可隐式调用的单参构造函数,使用列表初始化len
    mystring(const char* s = "") : len(strlen(s)) {
        buf = new char[len + 1];
        strcpy(buf, s);
    }

    // 析构函数
    ~mystring() {
        delete[] buf;
    }

    // 拷贝构造函数
    mystring(const mystring& other) : len(other.len) {
        buf = new char[len + 1];
        strcpy(buf, other.buf);
    }

    // 赋值运算符重载
    mystring& operator=(const mystring& other) {
        if (this != &other) {
            delete[] buf;
            len = other.len;
            buf = new char[len + 1];
            strcpy(buf, other.buf);
        }
        return *this;
    }

    // 复制函数 - 接受mystring对象
    void copy(const mystring& other) {
        delete[] buf;
        len = other.len;
        buf = new char[len + 1];
        strcpy(buf, other.buf);
    }

    // 复制函数 - 接受C风格字符串
    void copy(const char* s) {
        delete[] buf;
        len = strlen(s);
        buf = new char[len + 1];
        strcpy(buf, s);
    }

    // 追加函数 - 接受mystring对象
    void append(const mystring& other) {
        char* temp = new char[len + other.len + 1];
        strcpy(temp, buf);
        strcat(temp, other.buf);
        
        delete[] buf;
        buf = temp;
        len += other.len;
    }

    // 追加函数 - 接受C风格字符串
    void append(const char* s) {
        int slen = strlen(s);
        char* temp = new char[len + slen + 1];
        strcpy(temp, buf);
        strcat(temp, s);
        
        delete[] buf;
        buf = temp;
        len += slen;
    }

    // 比较函数 - 接受mystring对象
    int compare(const mystring& other) const {
        return strcmp(buf, other.buf);
    }

    // 比较函数 - 接受C风格字符串
    int compare(const char* s) const {
        return strcmp(buf, s);
    }

    // 显示字符串
    void show() const {
        cout << buf << endl;
    }

    // 返回指定位置的字符
    char at(int pos) const {
        if (pos >= 0 && pos < len) {
            return buf[pos];
        }
        return '\0'; // 位置无效时返回空字符
    }
};

int main() {
    mystring str = "hello"; // 隐式调用单参构造函数
    mystring ptr = "world"; // 使用列表初始化len
    
    str.copy(ptr);
    str.copy("你好");
    
    str.append(ptr);
    str.append("你好");
    
    str.compare(ptr);
    str.compare("你好");
    
    str.show(); // 输出结果
    cout << str.at(0) << endl; // 输出第0个字符
    
    return 0;
}    

以下是对 mystring 类实现的详细解析,按功能模块和关键设计点逐一说明:
1. 类的私有成员
cpp
运行
private:
    char* buf;  // 指向存储字符串的堆空间
    int len;    // 记录字符串长度

设计目的:
使用动态内存分配(堆空间),避免固定大小数组的限制(如 char buf[256])。
len 存储字符串实际长度,避免重复调用 strlen() 提高效率。
2. 构造函数
cpp
运行
mystring(const char* s = "") : len(strlen(s)) {
    buf = new char[len + 1];
    strcpy(buf, s);
}

关键点:
单参构造函数:参数为 const char*,支持隐式类型转换(如 mystring str = "hello";)。
列表初始化:len(strlen(s)) 在对象构造前初始化 len,比在函数体中赋值更高效。
内存分配:new char[len + 1] 分配足够空间(含字符串结束符 '\0')。
字符串复制:strcpy 将输入字符串复制到堆空间。
3. 析构函数
cpp
运行
~mystring() {
    delete[] buf;
}

内存管理:释放 buf 指向的堆空间,防止内存泄漏。
若不定义析构函数,对象销毁时 buf 的内存不会自动释放。
4. 拷贝构造函数
cpp
运行
mystring(const mystring& other) : len(other.len) {
    buf = new char[len + 1];
    strcpy(buf, other.buf);
}

深拷贝:
分配新的内存空间,复制原对象的字符串内容。
避免浅拷贝(直接复制指针)导致多个对象共享同一块内存,析构时重复释放。
5. 赋值运算符重载
cpp
运行
mystring& operator=(const mystring& other) {
    if (this != &other) {
        delete[] buf;
        len = other.len;
        buf = new char[len + 1];
        strcpy(buf, other.buf);
    }
    return *this;
}

自我赋值检查:if (this != &other) 避免自我赋值时释放内存后再复制。
步骤:
释放当前对象的内存。
分配新内存并复制字符串内容(深拷贝)。
返回引用:支持链式赋值(如 a = b = c)。
6. 复制函数(copy)
cpp
运行
void copy(const mystring& other) { ... }
void copy(const char* s) { ... }

重载实现:
接受 mystring 对象:复制其 len 和 buf 内容。
接受 const char*:计算长度并复制字符串。
内存管理:
先释放当前 buf 的内存,再分配新内存,防止内存泄漏。
7. 追加函数(append)
cpp
运行
void append(const mystring& other) { ... }
void append(const char* s) { ... }

步骤:
计算新长度 len + other.len(或 len + strlen(s))。
分配临时空间 temp,复制原字符串和追加内容。
释放原 buf,将 temp 赋值给 buf。
动态扩展:避免固定大小数组的限制,但需注意频繁追加可能导致性能开销。
8. 比较函数(compare)
cpp
运行
int compare(const mystring& other) const { ... }
int compare(const char* s) const { ... }

使用 strcmp:
返回值:
< 0:当前字符串小于参数。
0:字符串相等。
> 0:当前字符串大于参数。
const 修饰:标记为常量成员函数,不修改对象状态。
9. 显示函数(show)
cpp
运行
void show() const {
    cout << buf << endl;
}

输出字符串:直接打印 buf,利用 cout 对 char* 的重载。
const 修饰:不修改对象状态。
10. 字符访问函数(at)
cpp
运行
char at(int pos) const {
    if (pos >= 0 && pos < len) {
        return buf[pos];
    }
    return '\0'; // 位置无效时返回空字符
}

边界检查:确保访问位置合法,避免越界。
安全性:返回 '\0'(而非未定义行为),增强程序健壮性。
11. 主函数测试
cpp
运行
int main() {
    mystring str = "hello"; // 隐式构造
    mystring ptr = "world";
    
    str.copy(ptr);          // 复制 "world"
    str.copy("你好");        // 复制 "你好"
    
    str.append(ptr);        // 追加 "world"
    str.append("你好");      // 追加 "你好"
    
    str.compare(ptr);       // 比较
    str.compare("你好");     // 比较
    
    str.show();             // 输出:你好world你好
    cout << str.at(0) << endl; // 输出:你
}

功能验证:依次测试构造、复制、追加、比较、显示和字符访问。
总结
该实现通过动态内存管理和深拷贝机制,解决了固定大小数组的限制和浅拷贝导致的内存问题。每个成员函数都遵循以下原则:

内存安全:避免泄漏和野指针。
功能完整:提供字符串操作的核心功能。
异常安全:边界检查和状态维护。
性能优化:减少不必要的内存操作和字符串长度计算。

通过这些设计,mystring 类实现了一个简单但功能完整的字符串管理系统。



简化易理解版本代码
 

#include <iostream>
#include <cstring>
using namespace std;

class mystring {
private:
    char* buf;
    int len;

public:
    mystring() {}

    mystring(const char* r);
    void copy(mystring r); 
    bool compare(mystring r);
    void append(mystring r);
    char at(int index);
    void show();
};

mystring::mystring(const char* r)
    : len(strlen(r)), buf((char*)calloc(1, len + 1)) {
    strncpy(buf, r, len);
}

void mystring::copy(mystring r) {
    if (len < r.len) {
        len = r.len;
        free(buf);
        buf = (char*)calloc(1, len + 1);
    }
    strncpy(buf, r.buf, len);
}

bool mystring::compare(mystring r) {
    return strcmp(buf, r.buf) == 0;
}

void mystring::append(mystring r) {
    len = len + r.len;
    char* temp = buf;
    buf = (char*)calloc(1, len + 1);
    strcpy(buf, temp);
    strcat(buf, r.buf);
}

char mystring::at(int index) {
    return buf[index];
}

void mystring::show() {
    cout << buf << endl;
}

int main(int argc, const char** argv) {
    mystring str = "hello";
    mystring ptr = "world";

    str.show();
    ptr.show();

    str.copy(ptr);
    str.show();

    str.copy("aefserfsrfgresfg");
    str.show();

    cout << (str.compare(ptr)) << endl;
    cout << (str.compare("world")) << endl;

    str.append(ptr);
    str.show();

    str.append("world");
    str.show();

    cout << str.at(10) << endl;

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值