Why does static_cast(*this) to a base class create a temporary copy?
Asked Answered
D

4

27

I'm reading Effective C++ and came across this example:

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

  ...

};

The book says:

What you might not expect is that it does not invoke that function on the current object! Instead, the cast creates a new, temporary copy of the base class part of *this, then invokes onResize on the copy!

Why does static_cast (above code) create a new copy? Why not just just use the base class part of the object?

Derangement answered 31/1, 2012 at 18:23 Comment(2)
If it was cast to static_cast<Window&>(*this).onResize();, then I think it would use the current object. (Note the &). Not sure though.Wun
static_cast<Window*>(this)->onResize(); should also work but of course Window::onResize(); is the correct one here.Stratovision
D
33

Because this code asks to create a new object. This code wants to make a Window object from *this — which can be done using the copy constructor of Window.

What you want instead is this:

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

This means I want to make a Window& from *this — which is an implicit conversion from a derived class' reference (*this is a SpecialWindow&) to a Window& reference.

However, it's better to just call the specific version of the member function onResize() you want to call:

Window::onResize(); // equivalent to this->Window::onResize();
Decretal answered 31/1, 2012 at 18:27 Comment(1)
'Why not just just use the base class part of the object?' – wouldn't be the true answer 'Because the standard specifies that way!'? It could do differently, but that's what we need to live with – for good or for bad (actually it broke an attempt of mine to solve a problem via function pointers to virtual base member function, which made me stumble upon here...).Arvad
T
8

That's because the code is casting to a value Window instead of a reference Window&. According to the standard, this form of casting is equivalent to calling (C++11 §5.2.9/4 = C++03 §5.2.9/2)

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

which invokes the copy-constructor of Window, and performs onResize on that copy.

(The proper way of calling a method of the superclass is

Window::onResize();

)

Than answered 31/1, 2012 at 18:28 Comment(0)
T
2

Because you are casting actual object not a pointer or reference. It's just the same way casting double to int creates new int - not reusing the part of double.

Tersina answered 31/1, 2012 at 18:27 Comment(0)
A
1

Contrast:

static_cast<Window>(*this)

with:

static_cast<Window&>(*this)

One calls the copy constructor, the other does not. Does that help?

Ames answered 31/1, 2012 at 18:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.