zoukankan      html  css  js  c++  java
  • 完善String类([]、 +、 += 运算符重载)、>>和<<运算符重载

    在前面文章中使用过几次String类的例子,现在多重载几个运算符,更加完善一下,并且重载流类运算符。

    []运算符重载

    +运算符重载

    +=运算符重载

    <<运算符重载
    >>运算符重载

    String.h:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
     
    #ifndef _STRING_H_
    #define _STRING_H_
    #include <iostream>
    using namespace std;

    class String
    {
    public:
        String(const char *str = "");
        String(const String &other);
        String &operator=(const String &other);
        String &operator=(const char *str);

        bool operator!() const;
        char &operator[](unsigned int index);
        const char &operator[](unsigned int index) const;

        friend String operator+(const String &s1, const String &s2);
        String &operator+=(const String &other);

        friend ostream &operator<<(ostream &os, const String &str);
        friend istream &operator>>(istream &is, String &str);
        ~String(void);

        void Display() const;
        int Length() const;
        bool IsEmpty() const;

    private:
        String &Assign(const char *str);
        char *AllocAndCpy(const char *str);
        char *str_;
    };

    #endif // _STRING_H_

    String.cpp:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
     
    #pragma warning(disable:4996)
    #include "String.h"
    #include <string.h>
    //#include <iostream>
    //using namespace std;

    String::String(const char *str)
    {
        str_ = AllocAndCpy(str);
    }

    String::String(const String &other)
    {
        str_ = AllocAndCpy(other.str_);
    }

    String &String::operator=(const String &other)
    {
        if (this == &other)
            return *this;

        return Assign(other.str_);
    }

    String &String::operator=(const char *str)
    {
        return Assign(str);
    }

    String &String::Assign(const char *str)
    {
        delete[] str_;
        str_ = AllocAndCpy(str);
        return *this;
    }

    bool String::operator!() const
    {
        return strlen(str_) != 0;
    }

    char &String::operator[](unsigned int index)
    {
        //return str_[index];
        //non const 版本调用 const版本

        return const_cast<char &>(static_cast<const String &>(*this)[index]);
    }

    const char &String::operator[](unsigned int index) const
    {
        return str_[index];
    }

    String::~String()
    {
        delete[] str_;
    }

    char *String::AllocAndCpy(const char *str)
    {
        int len = strlen(str) + 1;
        char *newstr = new char[len];
        memset(newstr, 0, len);
        strcpy(newstr, str);

        return newstr;
    }

    void String::Display() const
    {
        cout << str_ << endl;
    }

    int String::Length() const
    {
        return strlen(str_);
    }

    bool String::IsEmpty() const
    {
        return Length() == 0;
    }

    String operator+(const String &s1, const String &s2)
    {
        //int len = strlen(s1.str_) + strlen(s2.str_) + 1;
        //char* newstr = new char[len];
        //memset(newstr, 0, len);
        //strcpy(newstr, s1.str_);
        //strcat(newstr, s2.str_);
        //
        //String tmp(newstr);
        //delete newstr;
        String str = s1;
        str += s2;
        return str;
    }

    String &String::operator+=(const String &other)
    {
        int len = strlen(str_) + strlen(other.str_) + 1;
        char *newstr = new char[len];
        memset(newstr, 0, len);
        strcpy(newstr, str_);
        strcat(newstr, other.str_);

        delete[] str_;

        str_ = newstr;
        return *this;
    }

    ostream &operator<<(ostream &os, const String &str)
    {
        os << str.str_;
        return os;
    }

    istream &operator>>(istream &is, String &str)
    {
        char tmp[1024];
        cin >> tmp;
        str = tmp;
        return is;
    }

    main.cpp:

     C++ Code 
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    #include "String.h"
    #include <iostream>
    using namespace std;

    int main(void)
    {
        String s1("abcdefg");

        char ch = s1[2];
        cout << ch << endl;

        s1[2] = 'A';
        s1.Display();

        const String s2("xyzabc");
        ch = s2[2];
        //s2[2] = 'M'; Error
        s2.Display();


        String s3 = "xxx";
        String s4 = "yyy";

        String s5 = s3 + s4;
        s5.Display();

        String s6 = "aaa" + s3 + "sdfadfa" + "xxxx";
        s6.Display();

        s3 += s4;
        s3.Display();

        cout << s3 << endl;

        String s7;
        cin >> s7;
        cout << s7 << endl;

    if (!s7.IsEmpty())
    cout<<s7.Length()<<endl;

        return 0;
    }


    需要注意的是,不能将String类的构造函数声明为explicit,否则"xxx"; 编译出错;operator[] 的non const 版本调用了const 版本的实现,其中使用了static_cast和 const_cast 两种类型转换操作符,可以参考这里;operator+ 调用了operator+= 的实现;只能将流类运算符重载为友元函数,因为第一个参数是流类引用,不是String 类。

    通过实现这样一个字符串类,我们可以熟悉基本的内存管理与拷贝控制。

    参考:

    C++ primer 第四版
    Effective C++ 3rd
    C++编程规范

  • 相关阅读:
    Div+Css布局教程(-)CSS必备知识
    html表格设置
    wxAui Frame Management用法
    aui
    MySQL死锁
    InnoDB索引存储结构
    MySQL事务调优
    MySQL慢SQL语句常见诱因
    InnoDB的LRU淘汰策略
    InnoDB事务之redo log工作原理
  • 原文地址:https://www.cnblogs.com/alantu2018/p/8471060.html
Copyright © 2011-2022 走看看