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

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

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

  ...

};

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

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

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


person purepureluck    schedule 31.01.2012    source источник
comment
Если бы он был приведен к static_cast<Window&>(*this).onResize();, то я думаю, что он использовал бы текущий объект. (Обратите внимание на &). Хотя не уверен.   -  person Aaron McDaid    schedule 31.01.2012
comment
static_cast‹Window*›(this)-›onResize(); тоже должно работать, но, конечно, Window::onResize(); здесь правильный.   -  person Trass3r    schedule 08.03.2013


Ответы (4)


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

Вместо этого вы хотите следующее:

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

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

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

Window::onResize(); // equivalent to this->Window::onResize();
person sbi    schedule 31.01.2012

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

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

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

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

Window::onResize();

)

person kennytm    schedule 31.01.2012

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

person Krizz    schedule 31.01.2012

Контраст:

static_cast<Window>(*this)

с участием:

static_cast<Window&>(*this)

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

person mcmcc    schedule 31.01.2012