标签:style blog color io os ar for sp div
本博文 我们通过 重新实现String类 来说明构造函数,复制控制,重载操作符。
一、构造函数(包括析构函数):
1:默认构造函数;
2:用户自己定义的构造函数
注意:当用户自己定义时,也要明确显示默认构造函数,这是因为,当我们没有定义自己的构造函数时,编译器会为我们自动合成一个,而我们定义了构造函数时,编译器默认构造函数改为我们自己定义的。这时就有可能出现错误;
3:析构函数;
具体声明与实现,代码如下:
1 声明部分: 2 String(); 3 String(const char*s); //by user 4 String(const String &s); //by user 5 ~String(); 6 实现部分: 7 String::String() 8 :str_(new char[1]) 9 { *str_ = 0; } 10 11 String::String(const char*s) 12 :str_(new char[strlen(s)+1]) 13 { 14 cout << "constructed by user" << endl; 15 ::strcpy(str_, s); 16 } 17 18 String::String(const String &s)//复制构造函数 19 :str_(new char[s.size()+1]) 20 { 21 cout << "copy" << endl; 22 ::strcpy(str_, s.str_); 23 } 24 25 String::~String()//将delete[] 放入析构函数中是为了防止悬浮指针 26 { 27 cout << "~construct" << endl; 28 delete[] str_; 29 }
二、复制控制(见上个博文);
三:重载运算符;
1)、 输入输出:
由于 输入输出流不可复制也不能复制,因此,形参和返回值只能为 引用 类型。
注意:为了与io标准库一致,操作符应接受i/ostream&作为第一个形参,对类类型const对象的引用作为第二个形参,并返回对 i/ostream 形参的引用。
输入时,要注意检查输入的内容是否合法;(注意inline的作用)
具体声明与实现 如以下代码:
声明: friend std::ostream &operator<<(std::ostream &os, const String &s); friend std::istream &operator>>(std::istream &is, String &s); 实现: inline std::ostream &operator<<(std::ostream &os, const String &s) { os << s.str_ ; return os;//no copy, no assignment;return reference } inline std::istream &operator>>(std::istream &is, String &s) { char tmp[1024]; if(is >> tmp)//注意要检查错误 s.str_ = tmp; return is; }
2)、赋值操作符与复合赋值操作符的重载:
赋值操作符 = 必须是类的成员函数。
一般而言, = 、+= 应返回做操作数的引用。
具体声明与实现如下代码:
1 声明: 2 String& operator=(const char*s); 3 String& operator=(const String &s); 4 String& operator+=(const char*s); 5 String& operator+=(const String &s); 6 实现: 7 //赋值时必须判断左右操作数是否相同;否则delete[]将会把“自己”删除 8 String& String::operator=(const char*s) 9 { 10 cout << "assignment" << endl; 11 if(str_ != s) 12 { 13 delete[] str_; 14 str_ = new char[strlen(s)+1]; 15 ::strcpy(str_ ,s); 16 } 17 return *this; 18 } 19 20 String& String::operator=(const String &s) 21 { 22 cout << "assignment" << endl; 23 if(this != &s)//attention 24 { 25 delete[]str_; 26 str_ = new char[s.size()+1]; 27 ::strcpy(str_, s.str_); 28 } 29 return *this; 30 } 31 //复合赋值的步骤: 32 //产生一个临时变量,将左右操作数复制于其中; 33 //删除原来的成员, 将临时变量copy至成员中 34 String& String::operator+=(const char*s) 35 { 36 cout <<"complex assignment" << endl; 37 char *st = new char[size()+strlen(s) +1]; 38 ::strcpy(st, str_); 39 ::strcat(st, s); 40 41 delete[]str_;//attention 42 str_ = st ; 43 44 return *this; 45 } 46 String& String::operator+=(const String &s) 47 { 48 cout << "complex assignment" << endl; 49 char *st = new char[size()+s.size()+1]; 50 ::strcpy(st, str_); 51 ::strcat(st, s.str_); 52 53 delete[]str_;//attention 54 str_ = st ; 55 56 return *this; 57 }
3)、加法运算符(+):
我们最好将 + 运算符声明为friend函数,因为若果声明为成员函数,则第一个参数 默认为本对象,这就可能限制 + 运算符的作用范围。
注意:这里我们用上述的 += 实现 +,这样可以不必 创建和赊销一个临时变量来保存+ 的结果;加法操作符不改变操作数的状态,所以我们将 操作数声明为 const对象的引用, 而 它产生并返回一个新的对象,该对象初始化为 第一个参数 const String &s1的副本。
实现如下:
1 声明; 2 friend String operator+(const String &s1, const String &s2); 3 friend String operator+(const String &s1, const char *str); 4 friend String operator+(const char *str , const String &s1); 5 实现: 6 String operator+(const String &s1, const String &s2) 7 { 8 String s(s1); 9 s += s2; 10 return s; 11 } 12 13 String operator+(const String &s1, const char *str) 14 { 15 String s(s1); 16 s += str; 17 return s; 18 } 19 20 String operator+(const char *str, const String &s1) 21 { 22 String s(s1); 23 s += str; 24 return s; 25 }
4)、关系运算符:
实现如下:
1 声明: 2 friend bool operator>(const String &s1, const String &s2); 3 friend bool operator>=(const String &s1, const String &s2); 4 friend bool operator<(const String &s1, const String &s2); 5 friend bool operator<=(const String &s1, const String &s2); 6 friend bool operator==(const String &s1, const String &s2); 7 friend bool operator!=(const String &s1, const String &s2); 8 实现: 9 bool operator>(const String &s1, const String &s2) 10 { 11 return ::strcmp(s1.str_, s2.str_)>0 ; 12 } 13 bool operator>=(const String &s1, const String &s2) 14 { 15 return !(s1 < s2); 16 } 17 bool operator<(const String &s1, const String &s2) 18 { 19 return !((s1 > s2)|| s1 == s2); 20 } 21 bool operator<=(const String &s1, const String &s2) 22 { 23 return !(s1 > s2) ; 24 } 25 bool operator==(const String &s1, const String &s2) 26 { 27 return ::strcmp(s1.str_, s2.str_)==0; 28 } 29 bool operator!=(const String &s1, const String &s2) 30 { 31 return !(s1 == s2);
5)、下标操作符 与 swap函数
下标操作符 最好 重载两个,因为 String 有 非const 和 const型。
而const型 是不允许修改的。
1 声明: 2 void swap(String &other); 3 char &operator[](size_t index); 4 const char operator[](size_t index)const; 5 6 size_t size()const 7 { return strlen(str_); } 8 const char *c_str()const 9 { return str_; } 10 实现: 11 char &String::operator[](size_t index) 12 { 13 return str_[index]; 14 } 15 16 const char String::operator[](size_t index)const 17 { 18 return str_[index]; 19 } 20 21 void String::swap(String &other) 22 { 23 std::swap(str_, other.str_);
完整代码如下:
1 //String.h 2 #ifndef STRING_H_ 3 #define STRING_H_ 4 5 #include <iostream> 6 #include <string.h> 7 8 //含有指针的类 9 class String 10 { 11 friend std::ostream &operator<<(std::ostream &os, const String &s); 12 friend std::istream &operator>>(std::istream &is, String &s); 13 friend String operator+(const String &s1, const String &s2); 14 friend String operator+(const String &s1, const char *str); 15 friend String operator+(const char *str , const String &s1); 16 friend bool operator>(const String &s1, const String &s2); 17 friend bool operator>=(const String &s1, const String &s2); 18 friend bool operator<(const String &s1, const String &s2); 19 friend bool operator<=(const String &s1, const String &s2); 20 friend bool operator==(const String &s1, const String &s2); 21 friend bool operator!=(const String &s1, const String &s2); 22 public: 23 String(); 24 String(const char*s); //by user 25 String(const String &s); //by user 26 ~String(); 27 28 String& operator=(const char*s); 29 String& operator=(const String &s); 30 String& operator+=(const char*s); 31 String& operator+=(const String &s); 32 33 void swap(String &other); 34 char &operator[](size_t index); 35 const char operator[](size_t index)const; 36 37 size_t size()const 38 { return strlen(str_); } 39 40 const char *c_str()const 41 { return str_; } 42 43 void print()const; 44 45 private: 46 char *str_; 47 }; 48 inline std::ostream &operator<<(std::ostream &os, const String &s) 49 { 50 os << s.str_ ; 51 return os;//no copy, no assignment;return reference 52 } 53 inline std::istream &operator>>(std::istream &is, String &s) 54 { 55 char tmp[1024]; 56 if(is >> tmp)//注意要检查错误 57 s.str_ = tmp; 58 return is; 59 } 60 61 #endif
String.cpp:
1 //String.cpp 2 #include "String.h" 3 4 #include <string.h> 5 #include <iostream> 6 using namespace std; 7 8 String::String() 9 :str_(new char[1]) 10 { *str_ = 0; } 11 12 String::String(const char*s) 13 :str_(new char[strlen(s)+1]) 14 { 15 cout << "constructed by user" << endl; 16 ::strcpy(str_, s); 17 } 18 19 String::String(const String &s)//复制构造函数 20 :str_(new char[s.size()+1]) 21 { 22 cout << "copy" << endl; 23 ::strcpy(str_, s.str_); 24 } 25 26 String::~String()//将delete[] 放入析构函数中是为了防止悬浮指针 27 { 28 cout << "~construct" << endl; 29 delete[] str_; 30 } 31 //赋值时必须判断左右操作数是否相同;否则delete[]将会把“自己”删除 32 String& String::operator=(const char*s) 33 { 34 cout << "assignment" << endl; 35 if(str_ != s) 36 { 37 delete[] str_; 38 str_ = new char[strlen(s)+1]; 39 ::strcpy(str_ ,s); 40 } 41 return *this; 42 } 43 44 String& String::operator=(const String &s) 45 { 46 cout << "assignment" << endl; 47 if(this != &s)//attention 48 { 49 delete[]str_; 50 str_ = new char[s.size()+1]; 51 ::strcpy(str_, s.str_); 52 } 53 return *this; 54 } 55 56 //复合赋值的步骤: 57 //产生一个临时变量,将左右操作数复制于其中; 58 //删除原来的成员, 将临时变量copy至成员中 59 String& String::operator+=(const char*s) 60 { 61 cout <<"complex assignment" << endl; 62 char *st = new char[size()+strlen(s) +1]; 63 ::strcpy(st, str_); 64 ::strcat(st, s); 65 66 delete[]str_;//attention 67 str_ = st ; 68 69 return *this; 70 } 71 String& String::operator+=(const String &s) 72 { 73 cout << "complex assignment" << endl; 74 char *st = new char[size()+s.size()+1]; 75 ::strcpy(st, str_); 76 ::strcat(st, s.str_); 77 78 delete[]str_;//attention 79 str_ = st ; 80 81 return *this; 82 } 83 84 String operator+(const String &s1, const String &s2) 85 { 86 String s(s1); 87 s += s2; 88 return s; 89 } 90 91 String operator+(const String &s1, const char *str) 92 { 93 String s(s1); 94 s += str; 95 return s; 96 } 97 98 String operator+(const char *str, const String &s1) 99 { 100 String s(s1); 101 s += str; 102 return s; 103 } 104 105 106 107 bool operator>(const String &s1, const String &s2) 108 { 109 return ::strcmp(s1.str_, s2.str_)>0 ; 110 } 111 bool operator>=(const String &s1, const String &s2) 112 { 113 return !(s1 < s2); 114 } 115 bool operator<(const String &s1, const String &s2) 116 { 117 return !((s1 > s2)|| s1 == s2); 118 } 119 bool operator<=(const String &s1, const String &s2) 120 { 121 return !(s1 > s2) ; 122 } 123 bool operator==(const String &s1, const String &s2) 124 { 125 return ::strcmp(s1.str_, s2.str_)==0; 126 } 127 bool operator!=(const String &s1, const String &s2) 128 { 129 return !(s1 == s2); 130 } 131 132 char &String::operator[](size_t index) 133 { 134 return str_[index]; 135 } 136 137 const char String::operator[](size_t index)const 138 { 139 return str_[index]; 140 } 141 142 void String::swap(String &other) 143 { 144 std::swap(str_, other.str_); 145 } 146 void String::print()const 147 { 148 cout << str_ << endl; 149 }
main.cpp:
1 #include "String.h" 2 #include <iostream> 3 #include <string.h> 4 #include <assert.h> 5 #include <unistd.h> 6 using namespace std; 7 8 int main(int argc, const char *argv[]) 9 { 10 String s; 11 s.print(); 12 13 String s2("hello"); 14 s2.print(); 15 cout <<s2.size() << endl; 16 cout << s2.c_str() << endl; 17 /* 18 String s3; 19 cin >> s3; 20 cout << s3 << endl; //munmap_chunk()->invalid pointer 21 */ 22 String s4; //String s4 = "hello world" init 23 s4 = "hello world"; 24 cout << s4 << endl; 25 26 String s5; 27 s5 = s4 ; 28 cout << s5 << endl; 29 30 assert(s5 == s4); 31 assert(s5 != s2); 32 assert(s5 >= s2); 33 assert(s5 > s2); 34 assert(s2 < s5); 35 assert(s2 <= s5); 36 37 String t1 ; 38 t1 = "beij"; 39 t1 += "shangh"; 40 cout << t1 << endl; 41 42 String t2; 43 t2 = "shenzh"; 44 t1 += t2 ; 45 cout << t1 << endl; 46 47 t1[0]= ‘A‘; 48 cout << t1 << endl; 49 /* 50 const String t3 ="wnager"; // error const->k 51 t3[0]=‘l‘; 52 cout << t3 << endl; 53 */ 54 String u1 ,u2; 55 u1 = s2; 56 u2 = "wow"; 57 58 u1 = u2 + " my god"; 59 cout << u1 << endl; 60 61 u1 = t2 + u2 ; 62 cout << u1 << endl; 63 64 cout << "before:" ; 65 cout << s4 << " " << u2 << endl; 66 67 cout << "swap"<< endl; 68 u2.swap(s4); 69 cout << "after:"; 70 cout << s4 << " " << u2 << endl; 71 72 return 0; 73 }
测试结果如下:
1 //test result 2 test@ubuntu:~/xiaofei/0926overloading$ ./a.out 3 4 constructed by user 5 hello 6 5 7 hello 8 assignment 9 hello world 10 assignment 11 hello world 12 assignment 13 complex assignment 14 beijshangh 15 assignment 16 complex assignment 17 beijshanghshenzh 18 Aeijshanghshenzh 19 assignment 20 assignment 21 copy 22 complex assignment 23 assignment 24 ~construct 25 wow my god 26 copy 27 complex assignment 28 assignment 29 ~construct 30 shenzhwow 31 before:hello world wow 32 swap 33 after:wow hello world 34 ~construct 35 ~construct 36 ~construct 37 ~construct 38 ~construct 39 ~construct 40 ~construct 41 ~construct
C++之重载String ----- 构造函数、复制控制、重载操作符
标签:style blog color io os ar for sp div
原文地址:http://www.cnblogs.com/xfxu/p/3999315.html