WTL for MFC Programmers(3)

<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 728x15, 创建于 08-4-23MSDN */ google_ad_slot = "3624277373"; google_ad_width = 728; google_ad_height = 15; //--> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 160x600, 创建于 08-4-23MSDN */ google_ad_slot = "4367022601"; google_ad_width = 160; google_ad_height = 600; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>

ATL-style templates<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

Even if you can read C++ templates without getting a headache, there is two things ATL does that might trip you up at first. Take this class for example:

关于C++的模版定义,ATL有两个让人头疼的事情。注意以下的例子:

class CMyWnd : public CWindowImpl<CMyWnd>

{

...

};

That actually is legal, because the C++ spec says that immediately after the class CMyWnd part, the name CMyWnd is defined and can be used in the inheritance list. The reason for having the class name as a template parameter is so ATL can do the second tricky thing, compile-time virtual function calls.

上面的代码是合法,因为C++规定只要在class CMyWnd定义部分的后面,就可以使用CMyWnd,当然也可以将它用在基类表的定义中。这就是为什么类名可以像一个模板参数那样使用,也正是由于这样的特性,ATL就有了第二件狡猾的设计,编译时虚函数调用。

(如果在class CMyWnd的后面马上就可以使用CMyWnd,那么能不能让一个类作自己的子类呢?好像可以,其实是行不通的,因为编译器会去找基类的定义,如果自己做自己的基类,编译器会提示基类没有定义 蜗牛手记)

To see this in action, look at this set of classes:

注意看下面的类定义:

template <class T>

class B1

{

public:

    void SayHi()

    {

    T* pT = static_cast<T*>(this);   // HUH?? I'll explain this below

 

        pT->PrintClassName();

    }

protected:

    void PrintClassName() { cout << "This is B1"; }

};

 

class D1 : public B1<D1>

{

    // No overridden functions at all

};

 

class D2 : public B1<D2>

{

protected:

    void PrintClassName() { cout << "This is D2"; }

};

 

main()

{

D1 d1;

D2 d2;

 

    d1.SayHi();    // prints "This is B1"

    d2.SayHi();    // prints "This is D2"

}

The static_cast<T*>(this) is the trick here. It casts this, which is of type B1*, to either D1* or D2* depending on which specialization is being invoked. Because template code is generated at compile-time, this cast is guaranteed to be safe, as long as the inheritance list is written correctly. (If you wrote

class D3 : public B1<D2>

you'd be in trouble.) It's safe because the this object can only be of type D1* or D2* (as appropriate), and nothing else. Notice that this is almost exactly like normal C++ polymorphism, except that the SayHi() method isn't virtual.

语句static_cast<T*>(this)是一个骗局。它通过这个特殊的调用将类型是B1*this转换为D1*或者D2*。因为模板的代码是在编译时生成的,只要基类烈表示正确的,这种转换保证是安全的。(如果你写出这样的语句:class D3 : public B1<D2>,那你将于遇到麻烦)。这种安全是因为this对象只能根据定义转换为D1*D2*,而不能转换为其他的什么东西。这就像标准C++的多态性一样的,只是SayHi()函数不是虚函数而已。

<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 728x15, 创建于 08-4-23MSDN */ google_ad_slot = "3624277373"; google_ad_width = 728; google_ad_height = 15; //--> </script> <script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
<script type="text/javascript"><!-- google_ad_client = "pub-2947489232296736"; /* 160x600, 创建于 08-4-23MSDN */ google_ad_slot = "4367022601"; google_ad_width = 160; google_ad_height = 600; //--> </script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"> </script>
阅读更多
个人分类: VC和VC++
想对作者说点什么? 我来说一句

wtl_for_mfc_programmers

2010年11月03日 1.44MB 下载

WTL for MFC Programmers 中英文

2014年05月06日 2.03MB 下载

wtl_for_mfc_programmers_cn

2010年05月17日 1.44MB 下载

C++中WTL_和_MFC_编程

2011年03月25日 1.65MB 下载

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭