为什么允许这样做?

时间:2014-03-21 00:33:41

标签: c++ reference const overloading

所以我知道不允许使用具有相同参数和名称的函数:

int a(int b) {
    return b;
}
int a(int b) {
    return b;
}

int main() {
    int c = a(4);
}

以上不会编译。但后来我开始思考,如果我通过引用传递一个,然后按值传递一个怎么办?

int a(int b) {
    return b;
}
int a(int& b) {
    return b;
}

int main() {
    int c = a(4);
}

以上编译,我猜是因为你不能通过引用传递4,所以它假设你想要第一个a,这意味着编译器可以区分你想要的功能打电话。如果我然后将main更改为:

int main() {
    int c = a(4);
    a(c);
}

它将无法编译,我假设因为c可以传递给任一函数,所以编译器不知道要调用哪个函数。

但是......这个呢?

int a(const int& b) {
    return b;
}
int a(int& b) {
    return b;
}

int main() {
    int c = a(4);
    a(c);
}

这确实可以编译。为什么?我预计不会,因为c可以传递给第一个和第二个a。我有一些误解吗?

我的问题具体是,为什么这个(下面的代码)不编译,最后一个呢?

int a(int b) {
    return b;
}
int a(int& b) {
    return b;
}

int main() {
    int c = a(4);
    a(c);
}

如果我是编译器,并且我可以根据参数的匹配程度选择调用哪个函数,对于调用a(c),我可以从第一个和第二个中进行选择。是否有任何理由不能在此示例中选择第一个或第二个a

2 个答案:

答案 0 :(得分:8)

从函数调用中选择要使用的正确函数的过程称为过载分辨率。调用函数时,编译器将搜索具有该名称的所有函数(重载),并将它们编译为重载集。简而言之,通过从参数中选择需要最少转换的函数来选择最佳匹配。

这些是编译器从a(c)中选择的两个函数:

int a(const int& b);
int a(      int& b);

选择第二个重载是因为第一个重载需要const - 限定。您使用c调用函数的变量是非const,因此它与第二次重载完美匹配,并且可以绑定到非const {{1}}参考。

答案 1 :(得分:2)

int a(const int& b) {
    return b;
}
int a(int& b) {
    return b;
}

int main() {
    int c = a(4);
    a(c);
}

当您使用a(4)进行调用时,4是一个文字,只有您的const reference版本可以绑定它,因此被调用的版本。

现在,当您致电a(c)时,c作为非常规 int,因此它会更喜欢使用非const的函数参考。