Re[24]: Книжка по UB
От: so5team https://stiffstream.com
Дата: 14.08.25 10:07
Оценка:
Здравствуйте, rg45, Вы писали:

R>Так и как можно проверить, каким образом дёрнули метод?


А нам не важно как именно дернули -- через обращение к vtable или путем прямого вызова.
Нам важно какой метод в итоге был вызван. Т.е. конкретный механизм вызова всего лишь скучная деталь реализации.

S>>Именно это определение и нарушается, когда мы рассматриваем ситуацию с вызовом виртуальных методов в конструкторах/деструкторах. В С++.


R>Если не трудно, можно ещё раз указать пункт, который нарушается?


struct s1 {
  virtual void f() { std::cout << "s1::f" << std::endl; }

  s1() {
    this->f(); // (1)
  }

  void call_f() {
    this->f(); // (3)
  }
};

struct s2 : public s1 {
  void f() override { std::cout << "s2::f" << std::endl; }
};

int main() {
  s2 s; // (2)

  s.call_f(); // (4)
}


В точке (2) у нас конструируется объект типа s2, у которого должен быть собственный переопределенный f.

В точке (1) у нас на руках указатель на базовый тип s1 (это this через который идет вызов f).
Но в точке (1) вызов виртуального метода через указатель на базовый тип мы получаем не вызов s2::f, а вызов s1::f.

В точке (4) у нас все тот же объект типа s2.
Через вызов call_f мы приходим в точку (3), в которой у нас на руках опять указатель на базовый тип s1.
Однако, в точке (3) вызов виртуального метода через указатель на базовый тип мы получаем вызов s2::f, а не s1::f.

Тогда как в Java, Ruby или Python (подозреваю, что и в C#, и в D) мы в точках (1) и (3) получим одинаковое поведение.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.