为什么static_cast(* this)到基类创建临时副本?

时间:2012-01-31 18:23:02

标签: c++ casting effective-c++

我正在阅读 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(上面的代码)会创建一个新副本?为什么不只是使用对象的基类部分?

4 个答案:

答案 0 :(得分:30)

因为此代码要求创建一个新对象。此代码希望从Window创建*this对象 - 可以使用Window 复制构造函数 来完成。

你想要的是:

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

这意味着我想从Window&创建*this - 这是来自 派生类' <的 隐式转换em> reference *thisSpecialWindow&)到Window&引用。

但是,最好只需 调用要调用的成员函数的特定版本 onResize()

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

答案 1 :(得分:8)

这是因为代码转换为值Window而不是引用Window&。根据标准,这种形式的铸造相当于调用(C ++11§5.2.9/ 4 = C ++03§5.2.9/ 2)

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

调用Window的复制构造函数,并在该副本上执行onResize。

(调用超类方法的正确方法是

Window::onResize();

答案 2 :(得分:2)

因为您正在构建实际对象而不是指针或引用。 这与将double转换为int创建新int的方式相同 - 不重用double的部分。

答案 3 :(得分:1)

对比:

static_cast<Window>(*this)

使用:

static_cast<Window&>(*this)

一个调用复制构造函数,另一个不调用。这有帮助吗?