литерал `0` является допустимым кандидатом для int и const string & amp; перегрузки вызывают неоднозначный вызов

Недавно я исправил ошибку.

В следующем коде одна из перегруженных функций была константной, а другая - нет. Проблема будет решена, если обе функции сделать константными.

Мой вопрос: почему компилятор жаловался на это только тогда, когда параметр был равен 0.

#include <iostream>
#include <string>

class CppSyntaxA
{
public:
    void f(int i = 0) const { i++; }
    void f(const std::string&){}
};

int main()
{
    CppSyntaxA a;
    a.f(1);  // OK
    //a.f(0);  //error C2666: 'CppSyntaxA::f': 2 overloads have similar conversions
    return 0;
}
40
задан Paulw11 23 July 2019 в 22:40
поделиться

2 ответа

0 является особенным в C++. Нулевой указатель имеет значение 0, таким образом, C++ позволит преобразование 0 к типу указателя. Это означает, когда Вы звоните

a.f(0);

, Вы могли звонить void f(int i = 0) const с int со значением 0, или Вы могли звонить void f(const std::string&) с char* инициализированный к пустому указателю.

Обычно int версия была бы лучше, так как это - точное совпадение, но в этом случае int версия const, таким образом, это требует "преобразования" a к const CppSyntaxA, где std::string версия не требует такого преобразования, но действительно требует преобразования в [1 115] и затем в [1 116]. Это считают действительно изменением в обоих случаях, чтобы считаться равным преобразованием и таким образом неоднозначное. Создание обеих функций const или не const устранит проблему и int, перегрузка будет выбрана, так как это лучше.

56
ответ дан 26 November 2019 в 22:11
поделиться

Мой вопрос состоит в том, почему компилятор только жаловался на это, когда параметр был 0.

, поскольку 0 не только целочисленный литерал, но и это - также литерал нулевого указателя. 1 не литерал нулевого указателя, таким образом, нет никакой неоднозначности.

неоднозначность является результатом неявного конструктора преобразования std::string лет, который принимает указатель на символ как аргумент.

Теперь, преобразование идентификационных данных от интервала до интервала было бы иначе предпочтено преобразованию от указателя до строки, но существует другой аргумент, который включает преобразование: неявный объектный аргумент. В одном случае преобразование от CppSyntaxA& до CppSyntaxA&, в то время как в другом случае это CppSyntaxA& к const CppSyntaxA&.

Так, одна перегрузка предпочтена из-за одного аргумента, и другая перегрузка предпочтена из-за другого аргумента и таким образом нет никакой однозначно предпочтительной перегрузки.

проблема будет устранена путем создания обеих констант функций

, Если обе перегрузки будут const квалифицированы, то неявная объектная последовательность преобразования аргумента идентична, и таким образом одна из перегрузок однозначно предпочтена.

11
ответ дан 26 November 2019 в 22:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: