我在理解ATL / WTL代码中模板的用途方面遇到了很多麻烦。
当您查看WTL时,您会看到如下代码:
template <class TBase>
class CEditT : public TBase
{
...
};
typedef CEditT<ATL::CWindow> CEdit;
CEditT
?换句话说,在CEditT<T>
T
的情况下,CWindow
会在什么情况下实例化?
答案 0 :(得分:3)
这样你就可以覆盖ATL / WTL类调用的ATL::CWindow
中的方法。如果ATL::CWindow
中有一些您不喜欢的内容,则可以使用重写方法从ATL::CWindow
派生一个类,然后将新类作为TBase
传递。
例如,ATL::CWindow::CenterWindow
很长一段时间有一个错误,它没有正确地考虑多个监视器,我看到人们使用这种技术来覆盖CenterWindow
的固定实现。< / p>
答案 1 :(得分:2)
假设使用了组合物:
template <class TBase> class CEditT {
public:
TBase base;
...
};
这与以下内容没有什么不同:
template <class ITEM> class ListNode {
public:
ITEM item;
ListNode<ITEM> *next;
// ...
};
ListNode
可以继承ITEM
,就像CEditT
与TBase
一样,但缺点是ITEM
不能像int
那样基本类型ListNode
。另一方面,ITEM
然后 一种protected:
,这可能很有用。此外,它可以访问ITEM
的任何{{1}}部分。
答案 2 :(得分:1)
它可以利用Curiously Recurring Template Pattern。如果您创建CEditT
的派生类,则您的定义将为class CMyEdit : public CEditT<CMyEdit>
。通过静态地将this
指针强制转换为您的班级,CEditT
可以调用您的方法,而无需使用vtable。
答案 3 :(得分:0)
为什么一切在ATL / WTL中使用模板基类?
简而言之,要获得“奇怪的编译时多态形式” ,这要归功于一种设计模式(而不是C ++惯用语),人们可以将其称为“颠倒继承”。 >作为“指定基类的基类” 的技术,以“允许您将自己的类插入类层次结构” ,以实现专门化类型的灵活性“无需对任何特定的派生类进行硬编码实现” 。
在阅读了ATL and Upside-Down Inheritance - Understanding ATL's atypical design approach撰写并由Visual C ++ Developers Journal于1999年7月发表的出色文章Jim Beveridge之后,一切都应该变得清楚。这里是link to full not paginated copy of the same article(也在Wayback Machine中)。