我正在阅读 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(上面的代码)会创建一个新副本?为什么不只是使用对象的基类部分?
答案 0 :(得分:30)
因为此代码要求创建一个新对象。此代码希望从Window
创建*this
对象 - 可以使用Window
的 复制构造函数 来完成。
你想要的是:
static_cast<Window&>(*this).onResize();
// ^
// note the &
这意味着我想从Window&
创建*this
- 这是来自 派生类' <的 隐式转换em> reference (*this
是SpecialWindow&
)到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)
一个调用复制构造函数,另一个不调用。这有帮助吗?