• C++反复遗忘--自定义String类


    1. 在学习C++诡异的语法的时候,由于没有正式的使用C++作为工作使用的语言,所以经常遗忘,这就需要反复的学习。而C++的友元函数和运算符重载如果不经常使用,真的很容易忘记。
      1 #include <iostream>
      2 #include <cstring>
      3 
      4 using namespace std;
      5 
      6 class String
      7 {
      8 public:
      9     ~String();
     10     String();                  //无参
     11     String(const char *s);     //有参
     12     String(const String &obj); //拷贝
     13 
     14     String &operator=(const String &obj);
     15     String &operator=(const char *s);
     16 
     17     friend String operator+(const String &obj1, const String &obj2); // str1 + str2 全局函数实现(友元函数实现),也可以使用成员函数实现
     18 
     19     friend ostream &operator<<(ostream &out, const String &obj);
     20     friend istream &operator>>(istream &in, const String &obj);
     21 
     22     String &operator+=(const String &obj); //str1+=str2
     23     String &operator+=(const char *s);
     24 
     25     char &operator[](const int idx) const; //返回引用,可以利用下标修改内容
     26 
     27 private:
     28     char *_arr;
     29     unsigned int _len;
     30 };
     31 String::~String()
     32 {
     33     delete _arr;
     34     _arr = NULL;
     35 }
     36 String::String()
     37 {
     38     cout << "String()" << endl;
     39     _len = 0;
     40     _arr = new char[1];
     41 }
     42 String::String(const char *s)
     43 {
     44     cout << "String(const char *s)" << endl;
     45     _len = strlen(s);
     46     _arr = new char[_len + 1];
     47     strcpy(_arr, s);
     48 }
     49 String::String(const String &obj)
     50 {
     51     cout << "String(const String &obj)" << endl;
     52     _len = obj._len;
     53     _arr = new char[_len + 1];
     54     strcpy(_arr, obj._arr);
     55 }
     56 String &String::operator=(const String &obj)
     57 {
     58     cout << "operator=(const String&)" << endl;
     59     delete _arr;
     60     _len = obj._len;
     61     _arr = new char[_len + 1];
     62     strcpy(_arr, obj._arr);
     63     return *this;
     64 }
     65 String &String::operator=(const char *s)
     66 {
     67     cout << "oeprator=(const char*)" << endl;
     68     delete _arr;
     69     _len = strlen(s);
     70     _arr = new char[_len + 1];
     71     strcpy(_arr, s);
     72     return *this;
     73 }
     74 String operator+(const String &obj1, const String &obj2)
     75 {
     76     cout << "operator+(const String &, const String&)" << endl;
     77     String s;
     78     s._len = obj1._len + obj2._len;
     79     s._arr = new char[s._len + 1];
     80     strcpy(s._arr, obj1._arr);
     81     strcat(s._arr, obj2._arr);
     82     return s;
     83 }
     84 ostream &operator<<(ostream &out, const String &obj)
     85 {
     86     cout << "operator<<(ostream&, const String &obj)" << endl;
     87     out << obj._arr;
     88     return out;
     89 }
     90 istream &operator>>(istream &in, const String &obj)
     91 {
     92     cout << "operator>>(istream&, const String &obj)" << endl;
     93     in >> obj._arr;
     94     return in;
     95 }
     96 String &String::operator+=(const String &obj)
     97 {
     98     cout << "operator+=(const String &obj)" << endl;
     99     char *temp = _arr;
    100     _len += obj._len;
    101     _arr = new char[_len + 1];
    102     strcpy(_arr, temp);
    103     strcat(_arr, obj._arr);
    104     delete temp;
    105     return *this;
    106 }
    107 String &String::operator+=(const char *s)
    108 {
    109     cout << "operator+=(const char *s)" << endl;
    110     char *temp = _arr;
    111     _len += strlen(s);
    112     _arr = new char[_len + 1];
    113     strcpy(_arr, temp);
    114     strcat(_arr, s);
    115     delete temp;
    116     return *this;
    117 }
    118 char &String::operator[](const int idx) const
    119 {
    120     cout << "operator[]" << endl;
    121     return _arr[idx];
    122 }
    123 
    124 int main()
    125 {
    126     String s0;
    127     String s1("hello");
    128     String s2(s1);
    129     String s3 = s2;      //执行拷贝构造,类似于 String s2(s1)
    130     String s4 = "world"; //执行有参构造,类似于 String s1("hello")
    131 
    132     s0 = s3;     //执行operator=(const String &)
    133     s0 = "good"; //执行operator=(const char*)
    134 
    135     String s5 = s1 + s4;
    136     s5 = s1 + s4;       //执行operator+ 、String()、operator= 三个函数
    137     cout << s5 << endl; //输出 helloworld
    138     s5 += s1;
    139     cout << s5 << endl; //输出 helloworldhello
    140     s5 += "world";
    141     cout << s5 << endl; //输出 helloworldhelloworld
    142     char c0 = s5[0];
    143     cout << c0 << endl; //输出 h
    144     s5[0] = 'x';
    145     cout << s5 << endl; //输出 xelloworldhelloworld
    146     cin >> s5;          //输入 hahaha
    147     cout << s5 << endl; //输出 hahaha
    148 
    149     return 0;
    150 }

    对应以上代码的输出:

     1 oop % ./String
     2 String()
     3 String(const char *s)
     4 String(const String &obj)
     5 String(const String &obj)
     6 String(const char *s)
     7 operator=(const String&)
     8 oeprator=(const char*)
     9 operator+(const String &, const String&)
    10 String()
    11 operator+(const String &, const String&)
    12 String()
    13 operator=(const String&)
    14 operator<<(ostream&, const String &obj)
    15 helloworld
    16 operator+=(const String &obj)
    17 operator<<(ostream&, const String &obj)
    18 helloworldhello
    19 operator+=(const char *s)
    20 operator<<(ostream&, const String &obj)
    21 helloworldhelloworld
    22 operator[]
    23 h
    24 operator[]
    25 operator<<(ostream&, const String &obj)
    26 xelloworldhelloworld
    27 operator>>(istream&, const String &obj)
    28 hahaha               #此行为输入
    29 operator<<(ostream&, const String &obj)
    30 hahaha
    31 oop % 

    需要强调的是,运算符重载中有一个非常特殊的存在,那就是‘=’,它和拷贝构造函数有一定的功能重叠。当仅定义其中一个时(比如,只定义拷贝构造),使用‘=’运算符时同样不会报错,这是因为编译器对函数调用做了隐式转换。我的理解是,在不能完全肯定不会出错的情况下,要么就把各种情况下的函数都定义一遍,尽量不让编译器做出隐式转换,或者使用explicit关键字组织此类隐式转换。

    最后,你的每一句留言都让博主欣喜若狂。

  • 相关阅读:
    C#编程(七十三)----------浅析C#中内存管理
    C#高级编程小结
    C#编程(七十二)----------DynamicObject和ExpandoObject
    C#编程(七十一)----------DLR ScriptRuntime
    C#编程(七十)----------dynamic类型
    C#编程(六十九)----------DLR简介
    C#编程(六十八)----------LINQ小结
    C#编程(六十七)----------LINQ提供程序
    C#编程(六十六)----------表达式树总结
    python 显示上午下午
  • 原文地址:https://www.cnblogs.com/PPWEI/p/13686169.html
Copyright © 2020-2023  润新知