ATL Style 模板学习手记
ATL的模板定义有些让人看的眼花缭乱,如,
class CMyWnd : public CWindowImpl
{
...
};
据说,这样做是合法的,原因是C++的语法解释过,即使CMyWnd类只是被部分定义,类名CMyWnd已经被列入递归继承列表,是可以使用的。
将类名作为模板类的参数是因为ATL为了在编译期间的虚函数调用。而真正的虚拟函数,其多态性是在运行时刻决定的。
为此,做程序已观之:
// AtlTemplate.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
using std::cout;
using std::endl;
class Base
{
public:
void SayHi(){ PrintClassName(); }
protected:
void PrintClassName(){ cout
};
class D1 :public Base
{
public:
protected:
void PrintClassName(){ cout
private:
};
class D2:public Base
{
public:
protected:
private:
};
template
class BaseT
{
public:
void SayHi()
{
T* pT = static_cast(this);
pT-PrintClassName();
}
protected:
void PrintClassName(){ cout
};
class TD1 :public BaseT
{
public:
//protected:
void PrintClassName(){ cout
private:
};
class TD2 : public BaseT
{};
class TD3 : public BaseT
{
};
int _tmain(int argc, _TCHAR* argv[])
{
D1 d1;
D2 d2;
d1.SayHi();
d2.SayHi();
//---------
TD1 td1;
TD2 td2;
td1.SayHi();
td2.SayHi();
//----
TD3 td3;
td3.SayHi();
getchar();
return 0;
}
最后的输出结果:
My class name: Base
My class name: Base
My class name: TD1
My class name: BaseT
My class name: TD1
对于普通的类Base来说,在基类Base::SayHi()中调用PrintClassName()函数,只能调用自己看得到的函数: Base::PrintClassName
所以D1虽然也定义了PrintClassName,但是没有被调用。
如果将Base中的PrintClassName前面加上virtual,则结果又不一样了。结果D1调用的是自己类的函数D1::PrintClassName;
而后使用的模板,由于在基类中将this指针强制转化成子类,导致可以查看到子类的函数了。如果不用模板,如何能在基类中强制转化成子类呢?真是高明。