ATL Style 模板学习手记

来源:互联网 发布:java cp 返回值 编辑:程序博客网 时间:2024/05/17 08:42
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 << _T("My class name:/tBase") <};

class D1 :public Base
{
public:
protected:
void PrintClassName(){ cout << _T("My class name:/tD1") <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 << _T("My class name:/tBaseT") <};

class TD1 :public BaseT
{
public:
//protected:
void PrintClassName(){ cout << _T("My class name:/tTD1") <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指针强制转化成子类,导致可以查看到子类的函数了。如果不用模板,如何能在基类中强制转化成子类呢?真是高明。
原创粉丝点击