Это правда, разрешение перегрузки происходит перед проверкой доступности.Раздел 13.3 стандарта ([over.match]
) гласит:
Разрешение перегрузки - это механизм выбора наилучшей функции для вызова, учитывая список выражений, которые должны быть аргументами вызова и наборафункций-кандидатов, которые могут быть вызваны на основе контекста вызова.Критериями выбора наилучшей функции являются количество аргументов, то, насколько хорошо аргументы соответствуют списку параметров-типов функции-кандидата, насколько хорошо (для нестатических функций-членов) объект соответствует неявному параметру объекта и некоторые другиесвойства функции-кандидата.[Примечание: функция, выбранная по разрешению перегрузки, не гарантированно соответствует контексту.Другие ограничения, такие как доступность функции, могут сделать ее использование в контексте вызова некорректным.- конец примечания]
Обычное исправление - присвоить публичным и защищаемым функциям разные имена.
Обратите внимание, это иногда полезно, например:
class Blah
{
const std::string& name_ref;
Blah(const char*) = delete;
public:
Blah(const std::string& name) : name_ref(name) {}
void do_something_with_name_ref() const;
};
std::string s = "Blam";
Blah b(s); // ok
Обратите внимание, что name_ref
будет считываться только из, поэтому целесообразно сделать его const
.Тем не менее, ссылки const
могут привязываться к временным файлам, а привязка name_ref
к временным объектам будет зависать, что приведет к неопределенному поведению в do_something_with_name_ref()
.
Blah c("Kablooey!"); // would be undefined behavior
// the constructor overload makes this a compile error
Перегрузка частного конструктора предотвращает временнуюstd::string
от неявного построения и связывания.