Рассмотрим следующий код C ++
class A
{
public:
void doStuff() {};
void callStuff()
{
doStuff(true);
doStuff();
};
private:
void doStuff(bool doIt = false) {};
};
int main()
{
A a;
a.doStuff();
a.callStuff();
return 0;
}
Не удивительно, что при компиляции GCC выдает несколько ошибок:
overload.cpp: в функции-члене void A :: callStuff () ’: overload.cpp: 8: 10: ошибка: вызов перегруженной функции doStuff () неоднозначен DoStuff (); ^ overload.cpp: 8: 10: примечание: кандидаты: overload.cpp: 4: 12: note: void A :: doStuff () void doStuff () {}; ^ overload.cpp: 11: 12: note: void A :: doStuff (bool) void doStuff (bool doIt = false) {}; ^ overload.cpp: в функции int main (): overload.cpp: 17: 17: ошибка: вызов перегруженной функции doStuff () неоднозначен a.doStuff (); ^ overload.cpp: 17: 17: примечание: кандидаты: overload.cpp: 4: 12: note: void A :: doStuff () void doStuff () {}; ^ overload.cpp: 11: 12: note: void A :: doStuff (bool) void doStuff (bool doIt = false) {}; ^
У меня есть несколько вопросов:
main
Функция не должна иметь доступа к частной перегрузке, поэтому она должна знать, какую из них использовать.Как я могу сказать компилятору, какую перегрузку я хочу использовать? Я буду
вынужден удалить одного из них?
Вы не можете просто удалить или переименовать один из них.
Если мне нужно удалить один из них, как я могу найти эту проблему в
время компиляции, не пытаясь вызвать перегрузку? Пока я не
называя их все должно хорошо скомпилироваться, чтобы я мог только узнать
позже, что я не могу вызвать перегрузку, которую я добавил, как только я
пытаюсь это назвать.
Вы тоже не можете. Неоднозначность обнаруживается только при попытке вызвать функцию-член без аргументов. Даже если бы вы могли выполнить некоторые проверки времени компиляции, они должны быть очень конкретными, и было бы проще просто удалить или переименовать одну из перегрузок.
Почему возникает вторая ошибка? Основная функция не должна быть в состоянии
чтобы получить доступ к частной перегрузке, поэтому он должен знать, какой из них использовать.
К сожалению, разрешение перегрузки происходит до того, как учитываются спецификаторы доступа. Поэтому компилятор даже не принимает во внимание тот факт, что одна из перегрузок является частной: неоднозначный вызов обнаруживается еще до того, как это произойдет. Я действительно не знаю, почему это происходит таким образом, но это то, что говорит стандарт.
Причина всех ваших проблем связана с вашими определениями функций и их соответствующими вызовами.
Итак, во-первых, компилятор прав в том, что ваши вызовы функций неоднозначны, отсюда и ваши ошибки — поскольку он не может определить, какая версия требуется, исходя из вашего использования. Хотя функции-члены могут быть перегружены с одинаковыми именами в одной области видимости, они должны иметь разные подписи (подпись функции-члена состоит из имени функции-члена, а также типа и порядка параметров функции-члена).
Следовательно:
void doStuff() {};
void doStuff(bool doIt = false) {};
когда вызывается так:
doStuff();
эквивалентны, что приводит к неоднозначному вызову функции, так как компилятор не может определить, хотите ли вы вызвать:
void doStuff();
или же
void doStuff(boo doIt = false);
с неподдерживаемым значением параметра. Видимость функции не может быть проверена из-за той же проблемы.
Единственное вокруг этого — изменить имя одной из функций. или же подпись функций (при сохранении того же имени).
Следовательно, что-то вроде этого совершенно законно:
class A
{
public:
void doStuff() {};
void callStuff()
{
doStuff(1, true);
doStuff();
};
private:
void doStuff(int i, bool doIt = false) {};
};
int main()
{
A a;
a.doStuff();
a.callStuff();
return 0;
}
Таким образом:
К сожалению, разрешение перегрузки происходит до того, как
учтено. Следовательно, компилятор даже не учитывает
учитывать тот факт, что одна из перегрузок является частной: неоднозначность
найдено еще до того, как это произойдет.
Смотрите эту ссылку для дополнительной ссылки:
Вам необходимо удалить параметры по умолчанию «bool doIt = false».
class A
{
public:
void doStuff() {};
void callStuff()
{
doStuff(true);
doStuff();
};
private:
//void doStuff(bool doIt = false) {};
void doStuff(bool doIt) {};
};
int main()
{
A a;
a.doStuff();
a.callStuff();
return 0;
}