今天看《Effective C++ 3rd》中的第27款时看到的:
public:
virtual void onResize() { // derived onResize 实现代码
static_cast<Window>(*this).onResize(); // 将*this 转型为Window
// 然后调用其onResize
// 然而,这样可不行!
...
}
...
};
上面这段程序的结果会与预期效果有所偏差。问题出在何处?上面用红色标注的代码中,首先会如预期中将*this转型为Window,之后调用的onResize()函数也是基类版本,但是问题出在onResize()函数的所操作的对象,并不是*this对象中的基类对象,而是其一个临时副本。
正确的解决方案是放弃转型操作,而改用限定符:
Window:: onResize();
下面是一段试验代码,可以证明确实在如上的转型操作中存在一个充当副本的临时对象
程序的输出结果为
"关于强制转型的一件有趣的事,是很容易写出看起来似是而非(在其它语言中也许是对的)的代码。例如,许多应用程序框架要求 derived classes中的virtual member function要首先调用 base class(的对应函数。假设我们有一个 Window base class(基类)和一个 SpecialWindow derived class(派生类),它们都定义了 virtual function(虚拟函数)onResize。进一步假设 SpecialWindow 的 onResize 被期望首先调用 Window 的 onResize。这就是实现这个的一种方法,它看起来对,但实际上错:
class Window { // base class
public:
virtual void onResize() { ... } // base onResize 实现代码
...
};
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;
}
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 //该句输出证明了在转型过程中通过拷贝构造函数构造了一个副本
in ctor of Derived
in copy ctor of Base //该句输出证明了在转型过程中通过拷贝构造函数构造了一个副本