Веб-версияОткрыть в Telegram

Пост​​Ответ

5 августа 2026
Г
Грокаем C++
Ссылка
нажмите — покажем
​​Ответ #опытным 2 вещи нужно знать(помимо всего остального С++😆), чтобы правильно ответить на квиз выше: 1️⃣ Сокрытие имен Когда в классе объявляют метод с неким именем, все методы с этим именем из базовых классов становятся невидимыми (скрытыми), независимо от их параметров. То есть struct A { void func(const std::string&); }; struct B : A { void func(float); }; B b; у объекта b можно вызвать только флотовый вариант func. Почему так? Компилятор увидел вызов метода и должен выполнить overload resolution. Он видит, что у объекта b статический тип B и идет смотреть, какие методы из этого класса подходят для вызова. И вот здесь срабатывает ключевая особенность поиска. Компилятор ищет имя func по цепочке областей видимости — снизу вверх (от производного класса к базовому). Как только он находит хотя бы одно объявление с именем func, поиск по иерархии немедленно останавливается . Дальше вверх (в A) он уже не заглядывает. В классе B есть func(float) — имя найдено. Поиск завершён. В набор кандидатов для overload resolution попадает только B::func(float). Метод A::func(const std::string&) в этот набор даже не рассматривается — он остался за границей поиска. Поэтому: b.func(15.f); // OK: float b.func("hello"); // Compile Error 2️⃣ Вообще говоря, это сокрытие имен - это проблема с точки зрения привычного нам ООП. "У меня есть базовый класс, от которого я наследую функциональность. Почему я не могу использовать метод базового класса?" Сокрытие имен - процесс неявный. Но мы можем явно сказать, какой сокрытый метод мы как разработчики хотим видеть в наследнике. С помощью директивы using можно вернуть видимость методу базового класса в наследник: struct A { void func(const std::string&); }; struct B : A { using A::func; void func(float); }; B b; b.func(15.f); // OK b.func("hello"); // OK using A::func; позволяет компилятору увидеть метод, принимающий строку, и успешно вызывать его при передаче строкового литерала. Такой же прием кстати используется в реализации overloaded паттерна. Когда мы это знаем, правильные ответы находятся на поверхности: struct A { void func(const std::string&); // #1 }; struct B : A { void func(float); // #2 }; struct C : B { using A::func; void func(int); // #3 }; C c; B& b = c; c.func(3.14f); // вызывает #3 за счет неявного приведения float к int c.func(123); // вызывает #3 c.func("hello"); // вызывает #1 за счет using b.func(3.14f); // вызывает #2 Don't let others shadow you. Stay cool #cppcore
24 · 3.9K ·

Рядом в ленте

ГГрокаем C++Квиз Выберете правильные утверждения о вызовах в коде: struct A { void func(const std::string&); // #1 }; struct B : A { void func(float); // #2 }; struct C : BГГрокаем C++Опрос
это сообщение
ГГрокаем C++Мапим значения на типы. Ч1 #опытным Иногда требуется на основе какого-то рантайм значения, например перечисления, получить какой-то соответствующий тип. НапримеГГрокаем C++Мапим значения на типы. Ч2 #опытным Напомню проблему: enum class DataType: uint8_t { kInt32, kDouble, kUint64 }; template<typename T> T create_from_buffer(const

Открытая публичная лента из поискового индекса ChatCrawler — «Google по публичному Telegram»; обновляется по мере обхода площадки. Время — UTC.

Только публичный контент, официальный API Telegram. О проекте · Вопросы · Чего мы не делаем · Убрать страницу из выдачи · Каталог · Поиск · Как мы считаем