问题:
srting 类还具备 C 方式字符串的灵活性吗?还能直接访问单个字符嘛?类似于数组访问操作符 []?
- string 类最大限度的考虑了 C 字符串的兼容性
- 可以按照使用 C 字符串的方式使用 string 对象
string s = "a1b2c3d4e";
int n = 0;
for(int i=0; i<s.length; i++)
{
if( isdigit(s[i])) // [] 内置操作符
{
n++;
}
}
cout << n << endl; // 4
上面的程序在编译器都是合法的!
引发的思考:类的对象怎么支持数组的下标访问的?
试验:
class Test
{
public:
// ...
};
//main.c
Test t;
cout << t[1] << endl;
// error
// no match for 'operator[]' in 't[1]'
被忽略的事实:
- 数组访问操作符是C/C++中的内置操作符(既然这样就可以重载)。
- 其原生意义是数组访问,访问里面的一个元素,也就是 指针运算(就是地址的偏移量)
数组访问操作符本质就是指针运算
//等价代换
a[n] ---> *(a+n) ---> *(n+a) ---> n[a]
#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; // cout << a[i] << endl;
}
cout << endl;
for(int i=0; i<5; i++)
{
i[a] = i + 10; // a[i] = i + 10;
}
for(int i=0; i<5; i++)
{
cout << *(i + a) << endl; // cout << a[i] << endl;
}
return 0;
}
重载数组访问操作符(重载不能违背其原生意义!!!)
- 只能通过类的成员函数重载
- 重载函数能且仅能使用一个参数
- 可以定义不同参数的多个重载函数
class Test
{
int a[5];
public:
int& operator [](int i)
{
return a[i]
}
int& operator [](const char& s)
{
if( s == "1st")
{
return a[0];
}
else if( s == "2nd")
{
return a[1]
}
else if()
.....
}
};
//main.c
Test t;
for(int i=0; i<5; i++) //给类里面的数组赋初值
{
t[i] = i;
// int operator [](int i)
// 如果重载赋值操作符返回值不是引用,上面的调用会出现问题
// error:lvalue required as left operand of assigment
// 意思是操作符重载返回的是右值,不能出现在赋值符合的左边
// 这就是返回引用的解释
}
cout << t[2] << endl;
cout << t["2nd"] << endl;
//字符串作为下标访问的形式也是合法的 后面的高级语言是这样的,比如C#之类的(通过操作符重载实现的)
使函数调用返回的值可以作为左值的方法是用(引用这个办法)
建议:
C++工程中能不出现 * 就不要出现 *
小结
- String类最大程度的兼容了 C 字符串的用法
- 数组访问的重载能够使得对象模拟数组的行为
- 只能通过类的成员函数重载数组访问符
- 重载函数能且仅能使用一个参数