TGStat
TGStat
Введите текст для поиска
Расширенный поиск каналов
  • flag Russian
    Язык сайта
    flag Russian flag English flag Uzbek
  • Вход на сайт
  • Каталог
    Каталог каналов и чатов Региональные подборки Тематические подборки Платные каналы Поиск каналов
    Добавить канал/чат
  • Рейтинги
    Рейтинг каналов Рейтинг чатов Рейтинг публикаций
    Рейтинги брендов и персон
  • Аналитика
  • Поиск по публикациям
  • Мониторинг Telegram
  • Продвижение
    Реклама через Яндекс Бизнес Реклама в каналах через TGStat Agency Реклама на сайте TGStat.ru
Грокаем C++

5 Aug, 12:00

Открыть в Telegram Поделиться Пожаловаться

​​Ответ
#опытным

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

3k 0 23 20 58
Каталог
Каталог каналов и чатов Подборки каналов Поиск каналов Добавить канал/чат
Рейтинги
Рейтинг каналов Telegram Рейтинг чатов Telegram Рейтинг публикаций Рейтинги брендов и персон
API
API статистики API поиска публикаций API Callback
Наши каналы
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Почитать
Академия TGStat Исследование Telegram 2019 Исследование Telegram 2021 Исследование Telegram 2023
Контакты
Справочный центр Поддержка Почта Вакансии
Всякая всячина
Пользовательское соглашение Политика конфиденциальности Публичная оферта
Наши боты
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot