转型操作的中的一个陷阱

    今天看《Effective C++ 3rd》中的第27款时看到的:

     

    "关于强制转型的一件有趣的事,是很容易写出看起来似是而非(在其它语言中也许是对的)的代码。例如,许多应用程序框架要求 derived classes中的virtual member function要首先调用 base class(的对应函数。假设我们有一个 Window base class(基类)和一个 SpecialWindow derived class(派生类),它们都定义了 virtual function(虚拟函数)onResize。进一步假设 SpecialWindowonResize 被期望首先调用 WindowonResize。这就是实现这个的一种方法,它看起来对,但实际上错:

class Window {                              // base class
public:
  virtual void onResize() { ... }             // base onResize 实现代码
  ...
};


class SpecialWindow: public Window {        // derived class
public:
  virtual void onResize() {                   // derived onResize 实现代码
    static_cast<Window>(*this).onResize();  // 将*this 转型为Window
                                              // 然后调用其onResize
                                              // 然而,这样可不行!

    ...                                      
  }                                         
  ...

};

    上面这段程序的结果会与预期效果有所偏差。问题出在何处?上面用红色标注的代码中,首先会如预期中将*this转型为Window,之后调用的onResize()函数也是基类版本,但是问题出在onResize()函数的所操作的对象,并不是*this对象中的基类对象,而是其一个临时副本。

    正确的解决方案是放弃转型操作,而改用限定符:
    Window:: onResize();

下面是一段试验代码,可以证明确实在如上的转型操作中存在一个充当副本的临时对象
#include <iostream>

using namespace std;

class Base
{
public:
    Base()
{cout<<"in ctor of Base"<<endl;}
    Base(Base
&){cout<<"in copy ctor of Base"<<endl;}

    
virtual void foo(){}
}
;

class Derived:public Base
{
public:
    Derived()
{cout<<"in ctor of Derived"<<endl;}

    
virtual void foo()
    
{
    static_cast
<Base>(*this).foo();
    
int x;
    x
++;
    }


}
;

int main(int argc, char * argv[])
{
    Derived d;
    d.foo();
    
return 1;
}


程序的输出结果为

in ctor of Base
in ctor of Derived
in copy ctor of Base //该句输出证明了在转型过程中通过拷贝构造函数构造了一个副本


   

   
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值