Прежде чем пытаться описать семантику любой инструкции C++, вам нужно вернуться к наиболее фундаментальным концепциям C++ (которые представляют собой сложный вариант фундаментальных концепций C): C++ — это компилируемый язык со статической типизацией сильный>.
Как и в C, в C++ имена просматриваются и связываются во время компиляции: любое используемое имя должно ссылаться на видимое объявление. Единственные имена, которые могут быть найдены компилятором, — это имена в классе, обозначенном выражением. (Выражения — это синтаксические конструкции, они существуют на во время компиляции.)
В статически типизированном языке типы выражений являются статическими и вычисляются внутри каждой функции в соответствии с объявлениями.
C++ также поддерживает динамическую полиморфность через виртуальные функции; это не делает язык динамически типизированным; основные принципы неизменны: каждое выражение имеет тип, определяемый применением правил, основанных на его синтаксисе и видимых объявлениях (видимых именах объектов, функций и т. д.).
С динамическим полиморфным типом полиморфного объекта (объекты существуют во время времени выполнения), то есть типом, который был создан (имя класса конструктора, который выполнялся для построить объект) определяет, какое тело функции вызывается виртуальным вызовом. Это иногда называют поздним связыванием.
Позднее связывание не является проблемой здесь, в вашем неправильно сформированном коде, который даже не компилируется, не запускается и не вызывает какую-либо функцию во время выполнения для любого полиморфного объекта:
obj->f3(); // Error (though was expecting LB since f3 is virtual)
Когда obj
имеет тип указателя, obj->something
совпадает с (*obj).something
; а obj
— локальная переменная, определенная как
A* obj = (...something not relevant for the argument...);
поэтому obj
имеет тип A*
, а *obj
имеет тип A
, который является классом, определенным как:
class A
{
public:
void f1() {cout<<"A::f1"<<endl;}
virtual void f2() {cout<<"A::f2"<<endl;}
};
В классе, обозначенном выражением *obj
, нет объявления какого-либо члена f3
, видимого в классе. Поэтому вызов сформирован неправильно. Он недействителен во время компиляции, и компилятор отклоняет его.
И это полный анализ этой неправильно построенной строки. Остальное не имеет значения для статически типизированного языка. Производные классы, не названные в соответствующем коде (который является просто объявленным типом obj
и выражением, определяющим, где выполняется поиск имени, *obj
), не имеют значения. Это сущность статической типизации.
Кроме того, создание зависимости достоверности кода от других классов, не названных напрямую (классы, которые могут быть типом объекта, созданного во время выполнения, на который ссылается какое-либо выражение), сделает невозможным обнаружение даже простой опечатки во время компиляции.
person
curiousguy
schedule
26.11.2018
f3()
не является членомA
. Конец. - person Sam Varshavchik   schedule 25.11.2018