Re[25]: Книжка по UB
От: rg45 СССР  
Дата: 14.08.25 10:17
Оценка:
Здравствуйте, 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, без вариантов. Да, он может сделать этот вызов через механизм позднего связывания. Только зачем? Где тот пункт стандарта, который обязывает его сделать только так?
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 14.08.2025 10:18 rg45 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.