TGStat
TGStat
Type to search
Advanced channel search
  • flag English
    Site language
    flag Russian flag English flag Uzbek
  • Sign In
  • Catalog
    Channels and groups catalog Regional compilations Thematic compilations Платные каналы Search for channels
    Add a channel/group
  • Ratings
    Rating of channels Rating of groups Posts rating
    Ratings of brands and people
  • Analytics
  • Search by posts
  • Telegram monitoring
  • Promotion
    Advertising through Yandex Business Advertising in channels through TGStat Agency Advertising on TGStat.ru website
Грокаем C++

5 Aug, 12:00

Open in Telegram Share Report

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

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
Catalog
Channels and groups catalog Channels compilations Search for channels Add a channel/group
Ratings
Rating of Telegram channels Rating of Telegram groups Posts rating Ratings of brands and people
API
API statistics Search API of posts API Callback
Our channels
@TGStat @TGStat_Chat @telepulse @TGStatAPI
Read
Академия TGStat Telegram Research 2019 Telegram Research 2021 Telegram Research 2023
Contacts
Справочный центр Support Email Jobs
Miscellaneous
Terms and conditions Privacy policy Public offer
Our bots
@TGStat_Bot @SearcheeBot @TGAlertsBot @tg_analytics_bot @TGStatChatBot