运算符[]模糊性解析

operator[] ambiguity resolution

本文关键字:模糊性 运算符      更新时间:2023-10-16

此处没有。以下是我在一本书中遇到的一个类定义的片段:

double& operator[](int i);
double operator[](int i) const;

我的问题是:为什么这不是模棱两可的编译项目的文件时,编译器不会给出任何错误。此外,在以下内容中(例如,假设AnyClass包含一个valarray<double>对象,我想直接访问它):

AnyClass test;
cout << test[2]

编译器使用哪个版本?

这并不含糊,因为const是签名的一部分,可以用于重载解析。因此,如果在非常量对象上使用operator[],它会选择不带const的重载,因为这是最具体的重载。如果你在const对象上使用它,它会用const选择重载,因为这是唯一适用的重载。

如果在const对象上调用,将使用const版本,否则将使用另一个版本。

这就是编译器解决歧义的方法。

AnyClass test;
const AnyClass const_test;
std::cout << test[2];       // calls operator[](int)
std::cout << const_test[2]; // calls operator[](int) const

要理解这一点,您只需意识到参数上的const就足以消除调用的歧义:

#include <iostream>
void foo(char* ptr)
{
    std::cout << "mutable: " << ptr << std::endl;
}
void foo(const char* ptr)
{
    std::cout << "const: " << ptr << std::endl;
}
int main()
{
    const char* constHello = "hello";
    char mutableHello[] = "hello";
    foo(constHello);
    foo(mutableHello);
}

此打印:

const:你好
可变:你好

编译器将尽可能选择限制最小的重载。因此,如果在char*过载时使用char*,它将选择它;但如果没有,编译器将决定将其转换为const char*是可行的转换(显然,相反的情况并非如此)。

现在,非常简单的事情是,所有方法都传递一个this指针作为任何函数的第一个参数。为了简单起见,此参数是隐藏的。方法末尾的const限定了this参数。正如我们刚刚看到的,指针上的const足以消除重载的歧义,因此这将有效地工作。