10-使用中括号表示法访问字符
12.2.3 使用中括号表示法访问字符
对于标准C-风格字符串来说,可以使用中括号来访问其中的字符:
char city[40] = "Amsterdam";
cout << city[0] << endl; // display the letter A
在C++中,两个中括号组成一个运算符——中括号运算符,可以使用方法operator 来重载该运算符。通常,二元C++运算符(带两个操作数)位于两个操作数之间,例如2 +5。但对于中括号运算符,一个操作数位于第一个中括号的前面,另一个操作数位于两个中括号之间。因此,在表达式city[0]中,city是第一个操作数,[]是运算符,0是第二个操作数。
假设opera是一个String对象:
String opera("The Magic Flute");
则对于表达式opera[4],C++将查找名称和特征标与此相同的方法:
String::operator[](int i)
如果找到匹配的原型,编译器将使用下面的函数调用来替代表达式opera[4]:
opera.operator[](4)
opera对象调用该方法,数组下标4成为该函数的参数。
下面是该方法的简单实现:
char & String::operator[](int i)
{
return str[i];
}
有了上述定义后,语句:
cout << opera[4];
将被转换为:
cout << opera.operator[](4);
返回值是opera.str[4](字符M)。由此,公有方法可以访问私有数据。
将返回类型声明为char &,便可以给特定元素赋值。例如,可以编写这样的代码:
String means("might");
means[0] = 'r';
第二条语句将被转换为一个重载运算符函数调用:
means.operator[](0) = 'r';
这里将r赋给方法的返回值,而函数返回的是指向means.str[0]的引用,因此上述代码等同于下面的代码:
means.str[0] = 'r';
代码的最后一行访问的是私有数据,但由于operator 是类的一个方法,因此能够修改数组的内容。最终的结果是“might”被改为“right”。
假设有下面的常量对象:
const String answer("futile");
如果只有上述operator 定义,则下面的代码将出错:
cout << answer[1]; // compile-time error
原因是answer是常量,而上述方法无法确保不修改数据(实际上,有时该方法的工作就是修改数据,因此无法确保不修改数据)。
但在重载时,C++将区分常量和非常量函数的特征标,因此可以提供另一个仅供const String对象使用的operator版本:
// for use with const String objects
const char & String::operator[](int i) const
{
return str[i];
}
有了上述定义后,就可以读/写常规String对象了;而对于const String对象,则只能读取其数据:
String text("Once upon a time");
const String answer("futile");
cout << text[1]; // ok, uses non-const version of operator[]()
cout << answer[1]; // ok, uses const version of operator[]()
cin >> text[1]; // ok, uses non-const version of operator[]()
cin >> answer[1]; // compile-time error