第34课 数组操作符的重载

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[n] <----> *(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、 重载函数 能且仅能 使用一个参数
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值