从零开始学C++之运算符重载(三):完善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;
}

从零开始学C++之运算符重载(三):完善String类([]、 +、 += 运算符重载)、>>和<<运算符重载_第1张图片


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

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


参考:

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


你可能感兴趣的:(String类,运算符重载,流类运算符)