请看以下代码,我们有个Base和一个Derived类,它们都定义了virtual函数test,然后Derived的test调用了Base的test,下面是实现方式之一,它看起来是对的,但实际上是错的。
#include <iostream>
using namespace std;
class Base
{
public:
virtual void test()
{
cout << "Base::test() " << b << endl;
b = 1;
cout << "Base::test() " << b << endl;
}
protected:
int b;
};
class Derived : public Base
{
public:
virtual void test()
{
/*
* 将*this转型为Base,然后调用test,这种方式并非在当前对象身上调用Base::test()之后又在
* 该对象身上执行Derived的专属动作。而是在当前对象base class成分的副本上调用Base::test,
* 然后在当前对象身上执行Derived的专属动作。如果Base::test()对数据成员有更改,实际上更改的
* 是其副本,对该Derived对象没有影响。
*/
static_cast<Base>(*this).test();
// 这种方式才是调用Base::test作用于*this本身
//Base::test();
cout << "Derived::test() " << b << endl;
b = 2;
cout << "Derived::test() " << b << endl;
}
};
int main(void)
{
Derived d;
d.test();
system("pause");
return 0;
}
这段程序将*this转型为Base,对函数test的调用也因此调用了Base::test,但是它调用的并不是当前对象上的函数,而是稍早转型动作所建立的一个"*this对象之base class成分"的暂时副本上的test。
参考资料:
《Effective C++》 条款27 尽量少作转型动作
本文深入探讨了C++中基类和派生类之间通过模板转型进行函数调用的机制,指出转型可能导致函数调用的对象不是当前对象本身,而是对象的基类部分的临时副本。并通过实例代码解释了这种现象,并引用了《Effective C++》一书中的条款27来强调减少转型操作的重要性。

3889

被折叠的 条评论
为什么被折叠?



