zoukankan      html  css  js  c++  java
  • Coding之路——重新学习C++(6):一个String类

      这个String类是对运算符重载和以前知识的一个综合应用,提供了值语义、字符串读写、检查和不检查的访问、流I/O和字符串拼接等功能。

    1.String类的定义

    class String{
        //类型的定义
        struct Srep;        //表示能被几个同样值的String共享
        Srep *rep;
    publicclass Cref;         //实现下标运算,区别对待读操作和写操作
        class Range();   //范围错误时抛出的异常
    
        //构造、赋值和析构函数
        String();                                         //x = "";
        String(const char*);                       //x ="abc";
        String(const String&);                    //x = other_string;
        String& operator=(const char*);
        String& operator=(const String&);
        ~String();
        
        //带检查的访问运算符
        void check(int i) const{if(i < 0 || rep->sz < i) throw Range();}
        char read(int i) const{return rep->s[i];}
        void write(int i, char c){
            rep = rep->get_own_copy(); 
            rep->s[i] =c;
        }
        Cref operator[](int i){
            check(i);
            return Cref(*this, i);
        }
        char operator[](int i) const{
            check(i);
            return rep->s[i];
        }
        int size() const{return rep->sz;}
    
        //其他String操作
        String& operator+=(const String&);
        String& operator+=(const char*);
    
        friend ostream& operator<<(ostream&, const String&);
        friend istream& operator>>(ostream&, String&);
        friend bool operator==(const String& x, const char *s){
            return strcmp(x.rep->s, s)==0;
        }
        friend bool operator==(const String& x, const String& y){
            return strcmp(x.rep->s, y.rep->s)==0;
        }
    };
    String operator+(const String&, const String&);
    String operator+(const String&, const char*);
    String operator+(const char*, const String&);    

    2.Srep类:实现同样值的String类的共享

    struct String::Srep{
        char *s;        //到元素的指针
        int sz;           //字符个数
        int n;             //引用计数
    
        Srep(int nsz, const char *p){
            n = 1;
            sz = nsz;
            s = new char[sz + 1];
            strcpy(s, p);
        }
    
        ~Srep(){
            delete s;
        }
    
        Srep* get_own_copy(){        //实现写时复制。
            if(n == 1) return this;
            n--;
            return new Srep(sz, s);
        }
        void assign(int nsz, const char* p){
            if(sz != nsz){
                delete []s;
                sz = nsz;
                s = new char[sz + 1];
            }   
            strcpy(s, p);
        }
    private:
        Srep(const Srep&);
        Srep& operator=(const Srep&);
    };

     3.String的复制实现

    String::String(){                                 //空串为默认值
        rep = new Srep(0, "");
    }
    
    String::String(const String& x){         //拷贝构造函数
        x.rep->n++;
        rep = x.rep;
    }
    
    String::~String(){                              //析构函数
        if(--n == 0) delete rep;
    }
    
    String& operator=(const String& x){   //复制赋值
         x.rep->n++;
         if(--n == 0) delete rep;
         rep = x.rep;
         return *this;
    }
    
    String::String(const char *s){
        rep = new Srep(strlen(s), s);
    }
    
    String& operator=(const char *s){   //复制赋值
         if(rep->n == 1) 
            rep->assign(strlen(s), s);
         else{
            rep->n--;
            rep = new Srep(strlen(s), s);
        }
         return *this;
    }

    4.实现读和写的Cref

    class String::Cref{
        friend class String;
        String &s;
        int i;
        Cref(String &ss, int ii):s(ss), i(ii){}
    public:
        operator char() const{ return s.read(i);}
        void operator=(char c){s.write(i, c);}
    };

     下面是下标运算符的实例:

    void f(String &s, const String &r){
        char c1 = s[1];     //c1 = s.operator[](1).operator char()
        s[1] = 'c';             //s.operator[](1).operator=('c')
    
        char c2 = r[1];     //c2 = r.operator[](1)
        r[1] = 'd';             //错误:给const赋值,r.operator[](1) = 'd'
    }
        
  • 相关阅读:
    关于View的onMeasure()、onSizeChanged()、onLayout()、onDraw()调用顺序
    Android事件分发机制完全解析,带你从源码的角度彻底理解(上)
    Android事件分发机制完全解析,带你从源码的角度彻底理解(下)
    自定义View经常重写的方法
    为自己的自定义View添加额外属性
    自定义View常用的获取宽高信息
    用工厂流水线的方式来理解 RxJava 的概念
    发布开源项目到Maven 中心仓库
    Android应用架构之Retrofit使用
    docker新手入门(基本命令以及介绍)
  • 原文地址:https://www.cnblogs.com/xskCoder/p/3998076.html
Copyright © 2011-2022 走看看