第34课 数组操作符的重载
1. 字符串类的兼容性
(1)string类最大限度的考虑了C字符串的兼容性
(2)可以按照使用C字符串的方式使用string对象
string s = "abcedefg"; char c = s[i];
【编程实验】用C方式使用string类 34-1.cpp
#include <iostream> #include <string> using namespace std; int main() { string s = "a1b2c3d4e"; int n = 0; for(int i=0; i<s.length(); i++) { if(isdigit(s[i])) //通过C字符串方式使用string对象(即数组) { n++; } } cout << n << endl; //4 return 0; }
运行结果:
2. 类的对象如何支持数组的下标访问
(1)数组访问是C/C++中的内置操作符
(2)数组访问符的原生意义是数组访问和指针运算
a[n] ←→ *(a + n) ←→ *(n + a) ←→ n[a]
【实例分析】指针和数组的复习 34-2.cpp
#include <iostream> #include <string> using namespace std; int main() { int a[5] = {0}; for(int i=0; i< 5; i++) { a[i] = i; } for(int i=0; i< 5; i++) { //指针方式的访问数组,比较不直观! //而下标访问的使用,可以隐藏对指针的操作 cout << *(a + i) << endl; //cout<< a[i] << endl; } cout << endl; for (int i=0; i<5; i++) { i[a] = i + 10; //a[i] = i + 10; } for (int i=0; i<5; i++) { cout << *(i + a) << endl; //cout<< a[i] << endl; } return 0; }
运行结果:
3. 重载数组访问的操作符:[]
(1)只能通过类的成员函数重载
(2)重载函数能且仅能使用一个参数
(3)可以定义不同参数的多个重载函数
(4)可以隐藏对指针的操作
【编程实验】重载数组访问操作符 34-4.cpp
#include <iostream> #include <string> using namespace std; class Test { private: int a[5]; public: //重载数组操作符,能且只能一个参数 //返回值为引用,可以作为左值使用!即, //Test t; //t[1] = 2; int& operator[](int i) { return a[i]; } int& operator[](const string& s) { if (s == "lst"){ return a[0]; } else if( s == "2nd"){ return a[1]; } else if( s == "3rd"){ return a[2]; } else if( s == "4th"){ return a[3]; } else if( s == "5th"){ return a[4]; } return a[0]; } int length(){return sizeof(a) / sizeof(*a);} };
int main() { Test t; for(int i = 0; i < t.length(); i++) { //通过下标方式访问对象,但本质上重载操作符 //是个函数,即t[i]是通过函数调用(而不是数组)来访问的 t[i] = i;//操作符[]返回的是引用,可以作为左值 } for(int i = 0; i < t.length(); i++) { cout << t[i] << endl; } cout << t["5th"] << endl; //4,t["5th"],本质上是个函数调用 cout << t["4th"] << endl; //3 cout << t["3rd"] << endl; //2 cout << t["2nd"] << endl; //1 cout << t["1st"] << endl; //0 return 0; }
运行结果:
【编程实验】数组类的完善 IntArray
//IntArray.h
#ifndef _INTARRAY_H_ #define _INTARRAY_H_ class IntArray { private: int m_length; int* m_pointer; //将构造函数变为私有的 IntArray(int len); bool construct(); //第2阶构造函数 public: static IntArray* NewInstance(int length);//提供创建对象的函数 int length(); bool get(int index, int& value); bool set(int index, int value); int& operator[](int index); IntArray& self(); //因为该类只能在堆在创建对象,为了操作方便 //通过这里返回对象的引用,可以避开指针操作的麻烦 ~IntArray(); }; #endif
//IntArray.cpp
#include "IntArray.h" IntArray::IntArray(int len) { m_length = len; } bool IntArray::construct() { bool ret = true; m_pointer = new int[m_length]; if (m_pointer) { for(int i = 0; i<m_length; i++) { m_pointer[i] = 0; } } else { ret = false; } return ret; } IntArray* IntArray::NewInstance(int length) { IntArray* ret = new IntArray(length); if(!(ret && ret->construct())) { delete ret; ret = 0; } return ret; } IntArray::~IntArray() { if(m_pointer) { delete[] m_pointer; } } int IntArray::length() { return m_length; } bool IntArray::get(int index, int& value) { bool bRet = (0 <= index) && (index <m_length); if(bRet) { value = m_pointer[index]; } return bRet; } bool IntArray::set(int index, int value) { bool bRet = (0 <= index) && (index <m_length); if(bRet) { m_pointer[index] = value; } return bRet; } int& IntArray::operator[](int index) { return m_pointer[index]; } IntArray& IntArray::self() { return *this; }
//main.cpp
#include <iostream> #include "IntArray.h" using namespace std; int main() { IntArray* a = IntArray::NewInstance(5); if(a != NULL) { //得到对象的引用,避免使用指针的麻烦。 //如使用引用方式访问第i个元素:array[i],很直观 //但使用指针方式访问第i个元素: (*a)[i], 不直观 IntArray& array = a->self(); cout << "array.length() = " << array.length() << endl; array[0] = 1; for(int i=0; i<array.length(); i++) { cout << array[i] << endl; } } delete a; return 0; }
运行结果:
4. 小结
(1)string类最大程序的兼容了C字符串的用法
(2)数组访问符的重载能够使得对象模拟数组的行为
(3)只能通过类的成员函数重载数组访问符
(4)重载函数能且仅能使用一个参数