Почему static_cast (* this) в базовый класс создает временную копию?

Я читаю Effective С++ и наткнулся на этот пример:

class Window {                                // base class
public:
  virtual void onResize() { ... }             // base onResize impl
  ...
};

class SpecialWindow: public Window {          // derived class
public:
  virtual void onResize() {                   // derived onResize impl;
    static_cast<Window>(*this).onResize();    // cast *this to Window,
                                              // then call its onResize;
                                              // this doesn't work!

    ...                                       // do SpecialWindow-
  }                                           // specific stuff

  ...

};

В книге говорится:

Что бы вы не ожидали, так это то, что он не вызывает эту функцию для текущего объекта! Вместо этого cast создает новую временную копию части базового класса * this, а затем вызывает onResize на копии!

Почему static_cast (выше код) создает новую копию? Почему бы просто не просто использовать базовый класс объекта?

Ответы

Ответ 1

Потому что этот код просит создать новый объект. Этот код хочет сделать объект Window из *this - это можно сделать с помощью конструктора copy Window.

Вместо этого вы хотите:

static_cast<Window&>(*this).onResize(); 
//                ^
//                note the &

Это означает, что я хочу сделать Window& из *this - который является неявным преобразованием из производного класса reference (*this является SpecialWindow&) до ссылки Window&.

Однако лучше просто вызвать определенную версию функции-члена onResize(), которую вы хотите вызвать:

Window::onResize(); // equivalent to this->Window::onResize();

Ответ 2

Это потому, что код отличает значение Window вместо ссылки Window&. Согласно стандарту, эта форма кастинга эквивалентна вызову (С++ 11 §5.2.9/4 = С++ 03 §5.2.9/2)

Window __t (*this);
__t.onResize();

который вызывает конструктор-копию Window и выполняет onResize в этой копии.

(Правильный способ вызова метода суперкласса

Window::onResize();

)

Ответ 3

Поскольку вы выполняете фактический объект, а не указатель или ссылку. Точно так же при нажатии double на int создается новый int - не повторное использование части double.

Ответ 4

Контрастность:

static_cast<Window>(*this)

с:

static_cast<Window&>(*this)

Один вызывает конструктор копирования, другой - нет. Это помогает?