C++中的数组操作符重载
1,本文讲述数组操作符重载,上篇博文的字符串类 string 确实强大,但 string 类 对象还具备 c 方式字符串的灵活性吗?还能直接访问单个字符吗?
1,c 方式字符串灵活性是指能够通过数组访问操作符方便的访问字符串中的单个字符;
2,字符串类的兼容性:
1,string 类最大限度的考虑了 c 字符串的兼容性;
2,可以按照使用 c 字符串的方式使用 string 对象;
3,代码示例:
1 string s = "a1b2c3d4e"; 2 int n = 0; 3 4 for(int i=0; i<s.length(); i++) 5 { 6 if( isdigit(s[i]) ) 7 { 8 n++; 9 } 10 }
3,用 c 方式使用 string 类编程实验:
1,main.cpp 文件:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 int main() 7 { 8 string s = "a1b2c3d4e"; 9 int n = 0; 10 11 for(int i = 0; i<s.length(); i++) 12 { 13 if( isdigit(s[i]) ) 14 { 15 n++; 16 } 17 } 18 19 cout << n << endl; 20 21 return 0; 22 }
2,输出结果:
4
3,在任意的 c++ 编译器中都支持数组访问的方式来使用字符串对象;
4,问题:
1,类的对象怎么支持数组的下标访问?
1,c++ 编译器并不支持将数组访问操作符和任意的类对象一起使用;
5,重载数组访问操作符:
1,数组访问符是 c/c++ 中的内置操作符;
1,数组访问操作符地位和 “+”、“-”、“*”、“/”、“==”、“=” 等内置操作符地位一致;
2,是操作符、地位同上,意味着可以重载;
2,数组访问符的原生意义是数组访问和指针运算;
1,a[n] <==> *(a + n) <==> *(n + a) <==> n[a];
1,指针和最终偏移地址相加,然后取元素;
2,加法交换律;
2,访问数组中的元素深层次的意义就是指针运算,算偏移量;
6,指针与数组的复习实例分析:
1,main.cpp 文件:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 int main() 7 { 8 int a[5] = {0}; 9 10 for(int i=0; i<5; i++) 11 { 12 a[i] = i; 13 } 14 15 for(int i=0; i<5; i++) 16 { 17 cout << *(a + i) << endl; // ==> cout << a[i] << endl; 18 } 19 20 cout << endl; 21 22 for(int i=0; i<5; i++) 23 { 24 i[a] = i + 10; // ==> a[i] = i + 10; 25 } 26 27 for(int i=0; i<5; i++) 28 { 29 cout << *(i + a) << endl; // cout << a[i] << endl; 30 } 31 32 return 0; 33 }
2,输出结果:
1 0 2 1 3 2 4 3 5 4 6 7 10 8 11 9 12 10 13 11 14
2,结论:
1,数组访问操作符原生语义是访问数组中的某个元素,深层次的意义是算地址的偏移量;
7,重载数组访问操作符:
1,数组访问操作符([]):
1,只能通过类的成员函数重载;
2,重载函数能且仅能使用一个参数;
1,参数可以是不同的类型;
3,可以定义不同参数的多个重载函数;
8,重载数组访问操作符编程实验:
1,main.cpp 文件:
1 #include <iostream> 2 #include <string> 3 4 using namespace std; 5 6 class test 7 { 8 int a[5]; // 被模拟的数组; 9 public: 10 int& operator [] (int i) // 能且仅能重载一个参数;引用是为了可以当做左值,因为不引用则直接是函数调用的返回值,它是不能当做左值使用的; 11 { 12 return a[i]; // 这里返回的不是局部变量,所以可以返回引用,且引用能够返回位置; 13 } 14 15 /* 通过字符串来访问数组 */ 16 int& operator [] (const string& s) // 定义多个重载函数;引用是为了可以当做左值; 17 { 18 if( s == "1st" ) 19 { 20 return a[0]; 21 } 22 else if( s == "2nd" ) 23 { 24 return a[1]; 25 } 26 else if( s == "3rd" ) 27 { 28 return a[2]; 29 } 30 else if( s == "4th" ) 31 { 32 return a[3]; 33 } 34 else if( s == "5th" ) 35 { 36 return a[4]; 37 } 38 39 return a[0]; 40 } 41 42 int length() 43 { 44 return 5; 45 } 46 }; 47 48 int main() 49 { 50 test t; 51 52 for(int i=0; i<t.length(); i++) 53 { 54 t[i] = i; 55 } 56 57 for(int i=0; i<t.length(); i++) 58 { 59 cout << t[i] << endl; 60 } 61 62 cout << t["5th"] << endl; // 通过字符串作为下标来访问数组; 63 cout << t["4th"] << endl; 64 cout << t["3rd"] << endl; 65 cout << t["2nd"] << endl; 66 cout << t["1st"] << endl; 67 68 return 0; 69 }
2,结论:
1,在以后工作中要学习 c++ 后续语言如 c#、d 等语言时,会发现确实可 以将字符串作为下标来访问一个数组,它就是应用了操作符重载来实现的;
9,数组类的完善编程实验:
1,intarray.h 文件:
1 #ifndef _intarray_h_ 2 #define _intarray_h_ 3 4 class intarray 5 { 6 private: 7 int m_length; 8 int* m_pointer; 9 10 intarray(int len); 11 intarray(const intarray& obj); 12 bool construct(); 13 public: 14 static intarray* newinstance(int length); 15 int length(); 16 bool get(int index, int& value); 17 bool set(int index ,int value); 18 int& operator [] (int index); // 数组访问操作符重载; 19 intarray& self(); // 返回自身,为了不使用指针; 20 ~intarray(); 21 }; 22 23 #endif
2,intarray.cpp 文件:
1 #include "intarray.h" 2 3 intarray::intarray(int len) 4 { 5 m_length = len; 6 } 7 8 bool intarray::construct() 9 { 10 bool ret = true; 11 12 m_pointer = new int[m_length]; 13 14 if( m_pointer ) 15 { 16 for(int i=0; i<m_length; i++) 17 { 18 m_pointer[i] = 0; 19 } 20 } 21 else 22 { 23 ret = false; 24 } 25 26 return ret; 27 } 28 29 intarray* intarray::newinstance(int length) 30 { 31 intarray* ret = new intarray(length); 32 33 if( !(ret && ret->construct()) ) 34 { 35 delete ret; 36 ret = 0; 37 } 38 39 return ret; 40 } 41 42 int intarray::length() 43 { 44 return m_length; 45 } 46 47 bool intarray::get(int index, int& value) 48 { 49 bool ret = (0 <= index) && (index < length()); 50 51 if( ret ) 52 { 53 value = m_pointer[index]; 54 } 55 56 return ret; 57 } 58 59 bool intarray::set(int index, int value) 60 { 61 bool ret = (0 <= index) && (index < length()); 62 63 if( ret ) 64 { 65 m_pointer[index] = value; 66 } 67 68 return ret; 69 } 70 71 int& intarray::operator [] (int index) // 数组访问操作符重载实现; 72 { 73 return m_pointer[index]; 74 } 75 76 intarray& intarray::self() // 返回数组指针的引用; 77 { 78 return *this; 79 } 80 81 intarray::~intarray() 82 { 83 delete[]m_pointer; 84 }
3,main.cpp 文件:
1 #include <iostream> 2 #include <string> 3 #include "intarray.h" 4 5 using namespace std; 6 7 int main() 8 { 9 intarray* a = intarray::newinstance(5); // 通过智能指针对象代替这里的指针; 10 11 if( a != null ) 12 { 13 intarray& array = a->self();//堆空间创建的对象,没有别名, 这里给它起一个别名; 14 15 cout << "array.length() = " << array.length() << endl; 16 17 array[0] = 1; 18 19 for(int i=0; i<array.length(); i++) 20 { 21 cout << array[i] << endl; 22 } 23 } 24 25 delete a; 26 27 return 0; 28 }
10,小结:
1,string 类最大程度的兼容了 c 字符串的用法;
2,数组访问符的重载能够使得对象模拟数组的行为;
3,只能通过类的成员函数重载数组访问操作符;
4,重载函数能且仅能使用一个参数;
上一篇: 单元测试JUnit