C++学习——重载下标运算符

重载下标运算符

引玉之砖

访问字符串中字符的一段代码:

#include <iostream>

using namespace std;

int main () {
    string s = "abcd"; // 声明字符串变量,并赋值
    cout << "s = " << s << endl;

    cout << "s[0] = " << s[0] << endl;
    cout << "s[1] = " << s[1] << endl;
    cout << "s[2] = " << s[2] << endl;
    cout << "s[3] = " << s[3] << endl;
    cout << "s[4] = " << s[4] << endl;
    // 显示了字符数组中的每一个字符,数组最后一个元素是0

    return 0;
}

运行结果应该如下:

s = abcd
s[0] = a
s[1] = b
s[2] = c
s[3] = d
s[4] =

C++ 中的string类型,本质上是一个类,并不是真正的字符串。它是对 C 风格字符串的封装。上述代码中的sstring类的对象。类本身并不能直接用于下标运算,那么为什么可以像上面那样访问string中的每一个字符呢?这是因为 C++ 标准库已经为string类重载了下标运算符,使得我们可以通过下标访问string对象中的各个字符。
让我们再来看一段代码:

#include <iostream>

using namespace std;

class Driver
{
private:
    string d_car[3];
public:
    string name;

    Driver() {d_car[0] = "Ferrari"; d_car[1] = "Porsche"; d_car[2] = "Tesla";}
    void show() {cout << "car[0]: " << d_car[0] 
                      << "\ncar[1]: " << d_car[1]
                      << "\ncar[2]: " << d_car[2] << endl;}
};

int main () {
    Driver d;
    d.show();

    return 0;
}

编译运行的结果应该如下:

car[0]: Ferrari
car[1]: Porsche
car[2]: Tesla

需求:现在要访问Driver对象d的私有成员car
思路1.把car成员设置为公有成员——不太规范。
思路2.写一个成员函数。修改后的代码如下:

#include <iostream>

using namespace std;

class Driver
{
private:
    string d_car[3];
public:
    string name;

    Driver() {d_car[0] = "Ferrari"; d_car[1] = "Porsche"; d_car[2] = "Tesla";}
    void show() {cout << "car[0]: " << d_car[0] 
                      << "\ncar[1]: " << d_car[1]
                      << "\ncar[2]: " << d_car[2] << endl;}
    string car(int num) { // 成员函数 car() 访问私有成员 d_car[]
        return d_car[num];
    }
};

int main () {
    Driver d;
    cout << "Car number 2 is a " << d.car(2) << endl;
    d.show();

    return 0;
}

运行结果如下:

Car number 2 is a Tesla
car[0]: Ferrari
car[1]: Porsche
car[2]: Tesla

如果函数的返回值是引用,就可以把函数调用的表达式当成变量来使用。进一步修改代码:

#include <iostream>

using namespace std;

class Driver
{
private:
    string d_car[3];
public:
    string name;

    Driver() {d_car[0] = "Ferrari"; d_car[1] = "Porsche"; d_car[2] = "Tesla";}
    void show() {cout << "car[0]: " << d_car[0] 
                      << "\ncar[1]: " << d_car[1]
                      << "\ncar[2]: " << d_car[2] << endl;}
    // 函数的返回值是引用,就可以把函数调用的表达式当成变量来使用
    string& car(int num) {
        return d_car[num];
    }
};

int main () {
    Driver d;
    // 既然可以当成变量来使用,那就可以修改变量的值。
    d.car(0) = "Tesla"; // 修改 d_car[0] 的值
    cout << "Car number 0 is a " << d.car(0) << endl;
    d.show();

    return 0;
}

编译运行的结果如下:

Car number 0 is a Tesla
car[0]: Tesla
car[1]: Porsche
car[2]: Tesla

以上方法有点奇怪,更好的方法是重载下标运算符

重载下标运算符

仅需改动两处,代码如下:

#include <iostream>

using namespace std;

class Driver
{
private:
    string d_car[3];
public:
    string name;

    Driver() {d_car[0] = "Ferrari"; d_car[1] = "Porsche"; d_car[2] = "Tesla";}
    void show() {cout << "car[0]: " << d_car[0] 
                      << "\ncar[1]: " << d_car[1]
                      << "\ncar[2]: " << d_car[2] << endl;}

    string& operator[](int num) { // 函数名换成 operator[]
        return d_car[num];
    }
};

int main () {
    Driver d;
    d[1] = "Tesla"; // 直接改成数组下标的写法
    cout << "Car number 1 is a " << d[1] << endl;
    d.show();

    return 0;
}

运行结果如下:

Car number 1 is a Tesla
car[0]: Ferrari
car[1]: Tesla
car[2]: Tesla

这就是下标运算符重载的效果。
string& operator[](int num) {...}
返回值类型& operator[](参数){...}
这种方法不仅可以访问数组元素,还可以修改数组元素
第二种方法是在成员函数的前面和后面都加const
const 返回值类型& operator[](参数) const {...}
这种方法只能访问元素,不能修改元素。常对象只能访问常函数,所以还需要创建一个常对象,代码如下:

#include <iostream>

using namespace std;

class Driver
{
private:
    string d_car[3];
public:
    string name;

    Driver() {d_car[0] = "Ferrari"; d_car[1] = "Porsche"; d_car[2] = "Tesla";}
    void show() {cout << "car[0]: " << d_car[0] 
                      << "\ncar[1]: " << d_car[1]
                      << "\ncar[2]: " << d_car[2] << endl;}

    string& operator[](int num) { // 函数名换成 operator[]
        return d_car[num];
    }

    const string& operator[](int num) const { // 函数名换成 operator[]
        return d_car[num];
    }
};

int main () {
    Driver d;
    d[1] = "Tesla"; // 直接改成数组下标的写法
    cout << "Car number 1 is a " << d[1] << endl;
    d.show();

    const Driver d1 = d;
    cout << "Car number 1 is a " << d1[1] << endl;

    return 0;
}

运行效果:

Car number 1 is a Tesla
car[0]: Ferrari
car[1]: Tesla
car[2]: Tesla
Car number 1 is a Tesla

在实际开发中,应该同时提供这两种形式,这样做是为了适应const对象,因为通过const对象只能调用const成员,若不提供第二种形式,那么将无法访问const对象的任何数组元素。

感谢浏览,一起学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值