您的位置:首页 > 其它

第34课 数组操作符的重载

2018-01-15 14:04 344 查看

1、字符串类的兼容性

    1.1、string类最大限度的考虑了C字符串的兼容性
    1.2、可以按照使用C字符串的方式使用string对象,如
    string  s  = "abcdefg" ;
    char  c  = s[i];

/********************          用C方式使用string类      ****************/
#include <iostream>
#include <string>
using namespace std;
int main()
{
    string s = "a1b2c3d4e5";
    int n = 0;
    
    for(int i=0; i<s.length(); i++)
    {                       //这样是为了兼容C语言
        if(isdigit(s[i]))//通过C字符串方式使用string对象(即数组)
        {
            n++;        //计算字符串中有几个数字,isdigit()函数,判断字符型是否为数字。
        }
    }
    
    cout << n << endl;  //5
    return 0;
}

2、类的对象如何支持数组的下标访问

    2.1、数组访问是C/C++中的内置操作符
    2.2、数组访问符的原生意义数组访问指针运算
        a
<----> *(a+n)指针加偏移量访问数组 <---->根据加法交换律*(n+a)  <------>   n[a]


/**********************        指针和数组的复习     *****************/
#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;   //a[i]
    }
    
    cout << endl;
    
    for (int i=0; i<5; i++)
    {
        i[a] = i;           //根据加法交换律
    }

    cout << endl;

    
    for(int i=0; i<5; i++)
    {
        //指针方式访问数组,比较不直观!而下标访问的使用,可以隐藏对指针的操作。
        cout<< *(i+a)<< endl;   //i[a]  等价于a[i]
    }
    
    return 0;
}

3、重载数组访问的操作符:[]

    3.1、只能通过类的成员函数重载      数组名
a 代表首元素的首地址类似 &a[0]。
    3.2、重载函数能且仅能使用一个参数
    3.3、可以定义不同参数的多个重载函数
    3.4、可以隐藏对指针的操作

/****************      重载数组访问操作符   ***************/
#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)   //s是一个string对象的引用
    {
        if(s == "1st"){
            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);
    }
};
/*
//通过数组的方式来访问string对象,操作后,对象里面的的一些成员方法可能不会更新,譬如string中的length()方法。
*/
int main()
{
    Test t; //对象
    
    for(int i=0; i<t.length(); i++)
    {
        //通过下标方式访问对象,但本质上重载操作符是个函数,即 t[i]是通过函数调用(不是数组)来访问的。类似  t.operator[](i) = i;
        //赋值给函数的返回值是不合法的。
        t[i] = i;   //操作符[]返回的是引用,可以作为左值。给数组元素初始化。
    }
    
    for(int i=0; i<t.length(); i++)
    {
        cout << t[i] << endl;
    }
    
    cout << endl;
    cout << "分隔符" << endl;
    cout << endl;
    
    cout << t["5th"] << endl;// 4 本质是函数调用。类似t.operator[]("5th") .
    cout << t["4th"] << endl;
    cout << t["3rd"] << endl;
    cout << t["2nd"] << endl;
    cout << t["1st"] << endl;//0
    
    return 0;
}

数组类的改进,重载了[]数组操作符、

//IntArray.h

#ifndef _TEST_H_
#define _TEST_H_
class IntArray
{
private:
    int m_length;
    int* m_pointer;
    IntArray(int leng);
    bool construct();   //二阶构造
public:
    static IntArray* NewInstance(int length);//提供创建对象的函数,二阶构造核心
    ~IntArray();
    int length();
    bool get(int index, int& value);
    bool set(int index, int value);
    int& operator[] (int pos);
    IntArray& self();//因为该类只能在堆空间上创建对象,为了操作方便通过这里返回对象的引用,可以避开操作指针的麻烦。
};
#endif

IntArray.cpp

#include "test.h"
#include <cstdlib>
int m_length;
int* m_pointer;
IntArray::IntArray(int leng)
{
    m_length = leng;
}
bool IntArray::construct()   //二阶构造
{
    bool ret = true;
    m_pointer = new int[m_length];  //只能申请int类型的数组类 。
    if(m_pointer)
    {
        for(int i=0; i<m_length; i++)
        {
            m_pointer[i] = 0;   //将数组初始化为0;
        }
    }
    else
    {
        delete[] m_pointer;
        ret = false;
    }
    return ret;
}
//函数是从属于类的,直接类名调用。
IntArray* IntArray::NewInstance(int length)//提供创建对象的函数,二阶构造核心
{
    IntArray* ret = new IntArray(length);//获得这个类
    if(!((ret) && (ret->construct())))    //调用二阶,构造数组
    {
        delete ret;
        ret = NULL;
    }
    return ret;
}
IntArray::~IntArray()
{
    if(!m_pointer)
    {
        delete[] m_pointer;
    }
}
int IntArray::length()
{
    return m_length;
}
bool IntArray::get(int index, int& value)
{
    bool ret = true;
    if((0<=index)&&(index<m_length))
    {
        value = m_pointer[index];
    }
    else
    {
        ret = false;
    }
    return ret;
}
bool IntArray::set(int index, int value)
{
    bool ret = ((0<=index)&&(index < m_length));
    if(ret)
    {
        m_pointer[index] = value;
    }
    return ret;
}
int& IntArray::operator[] (int pos)
{
    return m_pointer[pos];//返回引用可以做左值,重载操作符。
}
IntArray& IntArray::self()
{
    return *this;   //奇淫技巧,谁调用这个函数,将返回谁的引用。避免直接操作指针的麻烦。
}

main.cpp

#include <iostream>
#include <string>
#include "test.h"
using namespace std;
/****************     数组类      ***************/
int main()
{
    IntArray* ret = IntArray::NewInstance(5);
    if(ret != NULL)
    {//引用就是相当于在操作对象本身。
        IntArray& array = ret->self();//避免了直接操作指针的麻烦。通过指针获取对象的小技巧。
        cout << array.length() << endl;
        array[0] = 1;//其实质是array.operator[](0) = 1;
         for(int i=0; i<array.length(); i++)
         {
             cout << array[i] << endl;
         }
    }
/*
    //重载的操作符:
        int& IntArray::operator[](int index)
        {
            return m_pointer[index];
        }
总结:重载数组操作符时[],注意为了能具备做左值的资格,函数应该返回引用。
*/
    delete ret;
    return 0;
}

4、小结

    4.1、string类最大程度的兼容了C字符串的用法
    4.2、数组访问符的重载能够使得对象模拟数组的行为
    4.3、只能通过类的成员函数重载数组访问符
    4.4、重载函数能且仅能使用一个参数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: