Здравствуйте, so5team, Вы писали:
S>S>struct s1 {
S> virtual void f() { std::cout << "s1::f" << std::endl; }
S> s1() {
this->>f(); // (1)
S> }
S> void call_f() {
this->>f(); // (3)
S> }
S>};
S>struct s2 : public s1 {
S> void f() override { std::cout << "s2::f" << std::endl; }
S>};
S>int main() {
S> s2 s; // (2)
S> s.call_f(); // (4)
S>}
S>
S>В точке (2) у нас конструируется объект типа s2, у которого должен быть собственный переопределенный f.
S>В точке (1) у нас на руках указатель на базовый тип s1 (это this через который идет вызов f).
S>Но в точке (1) вызов виртуального метода через указатель на базовый тип мы получаем не вызов s2::f, а вызов s1::f.
S>В точке (4) у нас все тот же объект типа s2.
S>Через вызов call_f мы приходим в точку (3), в которой у нас на руках опять указатель на базовый тип s1.
S>Однако, в точке (3) вызов виртуального метода через указатель на базовый тип мы получаем вызов s2::f, а не s1::f.
В точке (3) компилятор не знает, какой будет метод вызван и вынужден использовать позднее связывание. А в точке (1) компилятор уже во время компиляции знает, что здесь может быть вызван только s1::f, без вариантов. Да, он может сделать этот вызов через механизм позднего связывания. Только зачем? Где тот пункт стандарта, который обязывает его сделать только так?