前面说到,c++的操作符重载是一项十分强大的功能,来看看对”[]”和”()”两个操作符的重载,这也是其强大的体现。
1. 重载中括号
”[]”在c/c++一般是实现取数组元素的值操作,”[]”内的数值为数组的下标,数组的下标为整数,如ar[0]、ar[7]。现在要实现的功能是重载”[]”使其支持下标是字符串类型的,如ar[“1st”],怎么做?
重载操作符的原则是不能改变操作符的原有语义和操作数的个数,”[]”用于取元素的值,且只有一个操作数,为括号内的值,这个是不可被改变的,但是括号内的值是针对该数组而操作的,所以”[]”操作符肯定有一个数组对象,这也就决定了对”[]”的重载实现的函数只能是类的成员函数,因为类的成员函数具有this指针,它可以指向对象本身(对象可以内含一个数组嘛)。
class cls
{
private:
int ar[6];
public:
cls();
int& operator[] (int i); //重载"[]"操作符
};
cls::cls()
{
int i;
for (i = 0; i < 6; i++)
{
ar[i] = i + 1;
}
}
int& cls::operator[] (int i) //返回引用,这样才可以对返回值赋值
{
return ar[i];
}
int main(void)
{
cls c;
printf("c[1] = %d\n", c[1]);
c[4] = 16;
printf("c[4] = %d\n", c[4]);
return 0;
}
编译运行:
从main()函数看,c是一个对象,却可以对对象利用”[]”进行下标操作,其实这也是可以对c++标准库中string类的对象进行”[]”操作的原因了。
实现到这一步了,要让”[]”内的操作数支持字符串类型,就easy了。
class cls
{
//...
public:
int& operator[] (int i); //重载"[]"操作符,"[]"内的操作数的操作数是int类型
int& operator[] (const char* str); //重载"[]"操作符,"[]"内的操作数是字符串类型
};
int& cls::operator[] (const char* str)
{
//1st 2nd 3rd 4th 5th
if (!strcmp("1st", str))
return ar[0];
if (!strcmp("2nd", str))
return ar[1];
if (!strcmp("3rd", str))
return ar[2];
if (!strcmp("4th", str))
return ar[3];
if (!strcmp("5th", str))
return ar[4];
if (!strcmp("6th", str))
return ar[5];
}
int main(void)
{
cls c;
printf("c[\"5th\"] = %d\n", c["5th"]);
c["2nd"] = 66;
printf("c[\"2nd\"] = %d\n", c["2nd"]);
return 0;
}
编译运行:
其实”[]”内的操作上数是字符串还是比较常见的,如c++标准库的map,其内部的实现机制也是类似如此吧。
2. 重载小括号
重载”()”也是一个十分有意思的操作。在c/c++中。”()”操作符表示的是一个函数调用符号,同样,它只能够通过类的成员函数来重载:
class cls
{
public:
void operator() () //重载"()"操作符,"()"内无操作数
{
printf("HelloWorld!\n");
}
void operator() (const char* str) //重载"()","()"内的操作数是字符串
{
printf("%s", str);
}
};
int main(void)
{
cls cc;
cc();
cc("Hello Linux\n");
return 0;
}
编译运行:
在main()函数中,cc是一个类,但是”cc();”这样的语法却是函数调用,在项目中这样的写法可以避免代码出现函数指针,至于在什么场合会使用到这种做法,估计会是在稍微大型的c++软件系统才需要吧,我尚未遇到,先了解有这么一种用法。
可以看出,c++的许多操作已经可以代替指针的使用了,这也难怪,在c++之后的语言,如java它不存在指针这个东西了。