Почему динамическое связывание может переопределить скрытие имени в C++?

Я узнал, что внутренние имена скрывают внешние имена (таким образом, перегрузка не выходит за рамки), потому что поиск имени идет перед сопоставлением типов. Поэтому я пишу следующий код C++ для игры с этим правилом:

class Base {
public:
    virtual void fcn() {}
};
class Derived : public Base {
public:
    void fcn(std::string s) {}
};

Base* bp = new Derived;
bp->fcn();
delete bp;

Согласно правилу сокрытия, Derived::fcn(std::string) функция должна скрывать Base::fcn(), Но приведенный выше код компилируется и работает правильно, вопреки правилу. Означает ли это, что динамическое связывание может переопределить скрытие имени в C++? Дело в том, если я изменю тип bp в Derived*, правило сокрытия действует, выдавая ошибку компиляции:

Derived::fcn: функция не принимает 0 аргументов

Не могли бы вы помочь мне объяснить это явление? В частности, может ли динамическое связывание переопределить скрытие имени, как я предположил? Если так, почему переопределение завершается ошибкой, если указатель указывает на производный класс? Спасибо.

1 ответ

Решение

Поиск имени (и разрешение перегрузки) происходит во время компиляции.

Дано bp->fcn, если тип bp является Base*, поиск имени будет изучать сферу Base а затем найти имя Base::fcn, Дело в том, что bp указывает на объект Derived не включает в себя, ни сфера Derived а потом Derived::fcn, Динамическая отправка происходит во время выполнения, если Derived имеет переопределенный Derived::fcn() он будет вызван во время выполнения.

Если тип bp является Derived*, поиск имени будет изучать сферу Derived а затем найти имя Derived::fcnзатем имя поиска останавливается, область действия Base больше не будет рассматриваться; имя скрывается

Другие вопросы по тегам