WTL for MFC Programmers(3)

WTL 专栏收录该内容
7 篇文章 0 订阅

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:

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

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值