ATL布幔之下的秘密(3)
2006-07-22 22:54:58 来源:WEB开发网核心提示: Drive::fun在模板的帮助下,我们可以实现与之相同的行为,ATL布幔之下的秘密(3)(10),程序50.#include <iostream>using namespace std;template <typename T>class Base {public
Drive::fun
在模板的帮助下,我们可以实现与之相同的行为。
程序50.
#include <iostream>
using namespace std;
template <typename T>
class Base {
public:
void fun() {
cout << "Base::fun" << endl;
}
void doSomething() {
T* pT = static_cast<T*>(this);
pT->fun();
}
};
class Drive : public Base<Drive> {
public:
void fun() {
cout << "Drive::fun" << endl;
}
};
int main() {
Drive obj;
obj.doSomething();
return 0;
}
程序的输出和前一个是一样的,所以我们可以用模板来模拟虚函数的行为。
程序中一个有趣的地方为
class Drive : public Base<Drive> {
这表明我们可以将Drive类作为一个模板参数来传递。程序中另外一个有趣的地方是基类中的doSomething函数。
T* pT = static_cast<T*>(this);
pT->fun();
在这里基类的指针被转换为派生类的指针,因为派生类是作为Base类的模板参数传递的。这个函数可以通过指针来执行,由于指针指向了派生类的对象,所以派生类的对象就被调用了。
但是这就有一个问题了:我们为什么要这样做?答案是:这样可以节省虚函数带有的额外开销,也就是虚函数表指针、虚函数表以及节省了调用虚函数所花费的额外时间。这就是ATL中使组件尽可能小、尽可能快的主要思想。
现在,你的脑海中可能会浮现另外一个问题。如果依靠这一开销更少的技术可以模拟虚函数的话,那我们为什么还要调用虚函数呢?我们不应该用这一技术替换所有的虚函数吗?对于这一问题,我可以简短地回答你:不,我们不能用这一技术替换虚函数。
更多精彩
赞助商链接