img snaill

WTL for MFC Programmers(3)

发表于2004/4/7 22:12:00  1149人阅读

分类: WTL

ATL-style templates

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:


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



    void SayHi()


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





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



class D1 : public B1<D1>


    // No overridden functions at all



class D2 : public B1<D2>



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





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()函数不是虚函数而已。

0 0



取 消