C++沉思录笔记 —— 第二十五章:库设计就是语言设计

初版String类库的设计

#include <cstring>

#include <iostream>

using namespace std;

class String{

public:

    String(const char* p){

        sz = strlen(p);

        data = new char[sz + 1];

        strcpy(data, p);

    }

    ~String() { delete[] data; }

    operator char*() { return data; } //类型转换函数的定义,String类型可自动转换为char*类型

private:

    int sz;

    char* data;

};

int main(int argc, char const *argv[])

{

    const char* p = "helloworld";

    String s(p);

    if(s)

        cout << s << endl;

    return 0;

}

以上有operator char*的返回值被交由用户去承担,这就是设计的不合理处。

第二版设计:

 

class String{

public:

    String(const char* p){

        sz = strlen(p);

        data = new char[sz + 1];

        if(data == 0)

            error();

        else

            strcpy(data, p);

    }

    ~String() { delete[] data; }

    operator char*() { return data; }

private:

    int sz;

    char* data;

};

 

此版设计中error能否返回给用户,都存在问题。
 
第三版设计:

class String{

public:

    String(const char* p){

        sz = strlen(p);

        data = new char[sz + 1];

        if(data == 0)

            error();

        else

            strcpy(data, p);

    }

    ~String() { delete[] data; }

    int valid() { return data != 0; }

    operator char*() { return data; }

private:

    int sz;

    char* data;

};

 
 

第四版设计:

#include <cstring>

#include <iostream>

using namespace std;

class String{

public:

    String(const char* p){

        sz = strlen(p);

        data = new char[sz + 1];

        if(data == 0)

            throw bad_alloc();

        else

            strcpy(data, p);

    }

    ~String() { delete[] data; }

    operator char*() { return data; }

private:

    int sz;

    char* data;

};

int main(int argc, char const *argv[])

{

    const char* p = "helloworld";

    try{

        String s(p);

        cout << s << endl;

    }catch(bad_alloc){

        return -1;

    }

    return 0;

}

 

这样的方式使用异常会极大地简化我们的程序,因为只要String存在,就能保证已经成功分配了String的内存。所以,不用在String类的别的地方检查内存耗尽了。

 

 

#include <iostream>

#include <cstring>

using namespace std;

class String{

public:

    friend String operator+(const String& op1, const String& op2);

    friend int operator==(const String& op1, const String& op2);

    friend ostream& operator<<(ostream& os, const String& s);

    String(): data(new char[1]){

        sz = 0;

        *data = '\0';

    }

    String(const char* p){

        assign(p, strlen(p));

    }

    String(const String& s){

        assign(s.data, s.sz);

    }

    String& operator=(const String& s){

        if(this != &s){

            delete[] data;

            assign(s.data, s.sz);

        }

        return *this;

    }

    operator const char*() const { return data; }

    //const char* make_cstring() const { return data; }

    int length() const { return sz; }

    void make_cstring(char* p, int len) const{

        if(sz <= len)

            strcpy(p, data);

        else

            throw("Not enough memory supplied");

        //...

    }

    String& operator+=(const String& s){

        char* odata = data;

        assign(data, sz + s.sz + 1);

        strcat(data, s.data);

        delete[] odata;

        return *this;

    }

    ~String() { delete[] data; }

private:

    int sz;

    char *data;

    void assign(const char* s, unsigned len){

        data = new char[len + 1];

        if(data == NULL)

            throw bad_alloc();

        sz = len;

        strcpy(data, s);

    }

};

String operator+(const String& op1, const String& op2)

{

    String ret(op1);

    ret += op2;

    return ret;

}

int operator==(const String& op1, const String& op2)

{

    return (strcmp(op1.data, op2.data) == 0);

}

ostream& operator<<(ostream& os, const String& s)

{

    return os << s.data;

}

int main(int argc, char const *argv[])

{

    String s("helloweiqianqian");

    const char* p = "helloweiqianqian";

    String t = p;

    cout << t << endl;

    cout << (s==t) << endl;

    return 0;

}

 

posted @ 2019-11-10 11:26    阅读(168)  评论(0)    收藏  举报