... // do SpecialWindow-
} // specific stuff
...
};
我突出了代码中的强制转型。(这是一个新风格的强制转型,但是使用旧风格的强制转型也于事无补。)正像你所期望的,代码将 *this 强制转型为一个 Window。因此调用 onResize 的结果就是调用 Window::onResize。你也许并不期待它没有调用当前对象的那个函数!作为替代,强制转型创建了一个 *this 的基类部分的新的,临时的拷贝,然后调用这个拷贝的 onResize!上面的代码没有调用当前对象的 Window::onResize,然后再对这个对象执行 SpecialWindow 特有的动作——它在对当前对象执行 SpecialWindow 特有的动作之前,调用了当前对象的基类部分的一份拷贝的 Window::onResize。如果 Window::onResize 改变了当前对象(可能性并不小,因为 onResize 是一个 non-const 成员函数),当前对象并不会改变。作为替代,那个对象的一份拷贝被改变。如果 SpecialWindow::onResize 改变了当前对象,无论如何,当前对象将被改变,导致的境况是那些代码使当前对象进入一种病态,没有做基类的变更,却做了派生类的变更。
解决方法就是消除强制转型,用你真正想表达的来代替它。你不应该哄骗编译器将 *this 当作一个基类对象来处理,你应该调用当前对象的 onResize 的基类版本。就是这样:
class SpecialWindow: public Window {
public:
virtual void onResize() {
Window::onResize(); // call Window::onResize
... // on *this
}
...
};
这个例子也表明如果你发现自己要做强制转型,这就是你可能做错了某事的一个信号。在你想用 dynamic_cast 时尤其如此。
对 dynamic_cast 的需要通常发生在这种情况下:你要在一个你确信为派生类的对象上执行派生类的操作,但是你只能通过一个基类的指针或引用来操控这个对象。有两个一般的方法可以避免这个问题。
|
您将承担一切因您的行为、言论而直接或间接导致的民事或刑事法律责任
留言板管理人员有权保留或删除其管辖留言中的任意内容 本站提醒:不要进行人身攻击。谢谢配合。 |