参考:http://www.weixueyuan.net/view/6384.html

总结:

  下标操作符是必须要以类的成员函数的形式进行重载的。其在类中的声明格式如下:
      返回类型 & operator[] (参数)
  或
      const 返回类型 & operator[] (参数) const    ,  后面的 const可使两函数是不同的函数,编译器可以分辨出来。

  如果使用第一种声明方式,操作符重载函数不仅可以访问对象,同时还可以修改对象。如果使用第二种声明方式,则操作符重载函数只能访问而不能修改对象。如语句“arr[5] = 7;”语句是无效的,

  非const成员函数不能处理const对象,这也是第二种的应用场景之一。

---------------------------

在前面已经提到下标操作符是必须要以类的成员函数的形式进行重载的。其在类中的声明格式如下:
    返回类型 & operator[] (参数)

    const 返回类型 & operator[] (参数)

如果使用第一种声明方式,操作符重载函数不仅可以访问对象,同时还可以修改对象。如果使用第二种声明方式,则操作符重载函数只能访问而不能修改对象。

在我们访问数组时,通过下标去访问数组中的元素并不具有检查边界溢出功能,我们可以重载下标操作符使之具有相应的功能。

例1:

#include<iostream>
#include<string>
using namespace std; class Array
{
public:
Array(){length = ; num = NULL;};
Array(int n);
int & operator[]( int );
const int & operator[]( int )const;
int getlength() const {return length;}
private:
int length;
int * num;
}; Array::Array(int n)
{
try
{
num = new int[n];
}
catch(bad_alloc)
{
cerr<<"allocate storage failure!"<<endl;
throw;
}
length = n;
} int& Array::operator[](int i)
{
if(i < || i >= length)
throw string("out of bounds");
return num[i];
} const int & Array::operator[](int i) const
{
if(i < || i >= length)
throw string("out of bounds");
return num[i];
} int main()
{
Array A();
int i;
try
{
for(i = ; i < A.getlength(); i++)
A[i] = i;
for(i = ;i < ; i++ )
cout<< A[i] <<endl;
}
catch(string s)
{
cerr<< s <<", i = "<< i <<endl;
} return ;
}

本例中定义了一个Array类,表示的是一个整形数组,在类中我们重载了下标操作符,使之具备检测下标溢出的功能。在类中为了方便我们使用了string类,这个类将在后面会进行详细介绍,在这里可以将其对象理解为一个字符串。在本例中重载下标操作符,我们提供了两个版本的重载下标操作符函数:
    int & operator[]( int );
    const int & operator[]( int )const;

需要注意的是第一个下标操作符重载函数最后面不带有const,加上const意味着该成员函数是常成员函数,如果第一个函数后面也加上了const,则两个函数仅有返回值不相同,这个不足以用于区分函数,编译器会提示语法错误。这两种版本的下标操作符重载函数其实很好理解,一个是可以修改类对象,下面一个则只可以访问对象而不能修改对象。对于上面一种下标操作符重载函数的声明,以下两个语句都是有效的:
    arr[5] = 7;
    int var = arr[3];

换言之,我们既可以访问类对象,同时又能修改类对象。“arr[5]”其实可以理解为:
    arr.operator[]( 5 )

而对于下面一种下标操作符重载函数,我们不能修改对象,也就是说语句“arr[5] = 7;”语句是无效的,但是它依然可以用于访问对象,因此“int var = arr[3];”语句仍然有效。

我们再来看一下下标操作符重载函数的定义,在函数体内部,先进行下标越界检测,如果出现越界则抛出异常,否则就返回下标 i 所对应的数据。这两种版本的下标操作符重载函数的函数定义都是如此。

我们来看一下程序输出结果:
    0
    1
    2
    3
    4
    out of bounds, i = 5

在例1中即使我们没有定义const版本的,上面的例子也是可以正确运行的,但是非const成员函数不能处理const对象,因此通常我们在设计程序时,会同时提供两种版本的操作符重载函数。在例1中如果我们增添下面一个display顶层函数,用于打印对象数组中的所有元素。

void display(const Array & A)
{
for(int i=; i < A.getlength(); i++)
cout<< A[i] <<endl;
}

此时如果我们在例1中没有定义const版本的下标操作符重载函数,则例1将会出现语法错误而无法编译通过的。

5.6 C++重载下标操作符的更多相关文章

  1. 【c++习题】【17/5/22】重载数组下标操作符

    一.写出程序运行结果 1#include <iostream > using namespace std; int a[10]={1,2, 3, 4, 5, 6, 7, 8, 9, 10} ...

  2. C++ 之 重载赋值操作符

    Widget 类中,定义了一个 Bitmap 类型的私有数据成员 -- pb 指针 class Bitmap { ... }; class Widget { private: Bitmap *pb; ...

  3. C++中复制构造函数与重载赋值操作符总结

    前言 这篇文章将对C++中复制构造函数和重载赋值操作符进行总结,包括以下内容: 1.复制构造函数和重载赋值操作符的定义: 2.复制构造函数和重载赋值操作符的调用时机: 3.复制构造函数和重载赋值操作符 ...

  4. C++中复制构造函数与重载赋值操作符

    我们都知道,在C++中建立一个类,这个类中肯定会包括构造函数.析构函数.复制构造函数和重载赋值操作:即使在你没有明确定义的情况下,编译器也会给你生成这样的四个函数.例如以下类:   class CTe ...

  5. 5.9 C++重载转型操作符

    参考:http://www.weixueyuan.net/view/6387.html 注意: 转型构造函数可以将其它类型的参数转换为类类型,如果我们要进行相反的转换过程,将类类型转换为其它数据类型, ...

  6. 5.5 C++重载赋值操作符

    参考:http://www.weixueyuan.net/view/6383.html 总结: 重载赋值操作符同重载类的是拷贝构造函数的原因是一样,将一个对象拷贝给另一个对象,同时当类中存在指针类型的 ...

  7. 【c++】c++中重载输出操作符,为什么要返回引用

    针对:ostream & operator <<(ostream & os, const ClassType &object) 说明几点: 1.第一个形参为对ost ...

  8. Effective C++(10) 重载赋值操作符时,返回该对象的引用(retrun *this)

    问题聚焦: 这个准则比较简短,但是往往就是这种细节的地方,可以提高你的代码质量. 细节决定成败,让我们一起学习这条重载赋值操作符时需要遵守的准则吧. 还是以一个例子开始: Demo // 连锁赋值 x ...

  9. C++ 重载操作符- 02 重载输入输出操作符

    重载输入输出操作符 本篇博客主要介绍两个操作符重载.一个是 <<(输出操作符).一个是 >> (输入操作符) 现在就使用实例来学习:如何重载输入和输出操作符. #include ...

随机推荐

  1. 《HTTP 权威指南》笔记:第十二章 基本认证体制

    导言 客户端可以通过网络来得到想要的信息,但是有一些信息并不能是对所有人都能看到的,因此必须有一种认证机制.服务器需要通过这种方式来了解用户身份,一旦服务器知道了用户的身份,就可以让用户能够访问请求的 ...

  2. 雷林鹏分享:jQuery EasyUI 树形菜单 - 创建异步树形菜单

    jQuery EasyUI 树形菜单 - 创建异步树形菜单 为了创建异步的树形菜单(Tree),每一个树节点必须要有一个 'id' 属性,这个将提交回服务器去检索子节点数据. 创建树形菜单(Tree) ...

  3. 【转载】MacOS下IntelliJ IDEA关联JDK1.8源码

    原文地址: MacOS下IntelliJ IDEA关联JDK1.8源码 1 打开jdk设置,找到具体添加的地方 2 找到自己jdk的源码位置替换掉 3 如果没有源码或者源码没有下载解压,自己下载解压, ...

  4. LeetCode--242--有效的字母异位词

    问题描述: 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的一个字母异位词. 示例 1: 输入: s = "anagram", t = "nagara ...

  5. p1470 Longest Prefix

    原本就想到dp,可是是我的思路是在串的各个位置都遍历一次set,看dp[i-st[k]]是否为1且前length(st[k])是st[k].这样200000*200*10会超时.更好的办法是在i位取前 ...

  6. hihocoder-1419 后缀数组四·重复旋律4 求连续重复次数最多的子串

    对于重复次数,如果确定了重复子串的长度len,那重复次数k=lcp(start,start+len)/len+1.而暴力枚举start和len的复杂度是O(n^2),不能接受.而有一个规律,若我们只枚 ...

  7. stylus笔记

    Stylus介绍及特点 基于Node.js的css的预处理框架,其本质上做的事情与 Sass/LESS 等类似, 可以以近似脚本的方式去写CSS代码,创建健壮的.动态的.富有表现力的CSS,默认使用 ...

  8. P3911 最小公倍数之和

    终于找到了一个只会用[gcd(i,j)==1] = sigema d|gcd(i,j) mu(d) 做不了的题. 考虑枚举gcd后. 此时,ans可以表示为一个 sigema x f(x)的形式. 考 ...

  9. laravel中常用的获取路径的函数

    1. app_path() // 获取app目录的路径 2. base_path() // 根目录的路径 3. config_path() // config目录的路径 4. public_path( ...

  10. 2018-2019 ACM-ICPC Brazil Subregional Programming Contest

    A:留坑 B:二维sg函数,特判边界情况 //#pragma GCC optimize(2) //#pragma GCC optimize(3) //#pragma GCC optimize(4) / ...