4

我在理解 ATL/WTL 代码中模板的用途时遇到了很多麻烦。

当您查看 WTL 时,您会看到如下代码:

template <class TBase>
class CEditT : public TBase
{
    ...
};

typedef CEditT<ATL::CWindow> CEdit;

为什么CEditT用模板基类定义?

换句话说,在什么情况下会CEditT<T>实例化 where Tis not CWindow

4

4 回答 4

3

这样您就可以覆盖ATL::CWindow由 ATL/WTL 类调用的方法。ATL::CWindow如果您不ATL::CWindow喜欢TBase.

例如,ATL::CWindow::CenterWindow很长一段时间以来都有一个错误,它没有正确考虑多个监视器,我看到人们使用这种技术来覆盖CenterWindow一个固定的实现。

于 2012-04-24T06:11:07.460 回答
2

假设使用组合代替:

template <class TBase> class CEditT {
public:
  TBase base;
  ...
};

这与以下内容没有太大区别:

template <class ITEM> class ListNode {
public:
   ITEM item;
   ListNode<ITEM> *next;
   // ...
};

ListNode可以改为继承ITEM,like CEditTdoes with TBase,但缺点是 thenITEM不能是基本类型 like int。另一方面, aListNode一种ITEM,这可能是有用的。此外,它可以访问protected:.ITEM

于 2012-04-23T02:50:05.497 回答
1

这样它就可以利用Curiously Recurring Template Pattern。如果您创建一个派生类,CEditT您的定义将是class CMyEdit : public CEditT<CMyEdit>. this通过将其指针静态转换为您的类,CEditT可以调用您的方法而无需使用 vtable。

于 2012-04-23T03:10:17.477 回答
0

为什么在 ATL/WTL 中一切都使用模板基类?

简而言之,为了实现一种“奇怪形式的编译时多态性”,这要归功于一种设计模式(而不是 C++ 习惯用法),可以将“颠倒继承”称为“指定基类的基类”的技术,以便“允许您将自己的类插入到类层次结构中”以实现专门类型的灵活性“无需对任何特定派生类进行硬编码实现”

在阅读了由Jim Beveridge撰写并于 1999 年 7 月由 Visual C++ Developers Journal 发表的优秀文章ATL 和 Upside-Down Inheritance -Understanding ATL's atypical design approach之后,这一切都应该清楚了。这里是同一篇文章的完整未分页副本的链接(也在 Wayback 机器中)。

于 2019-10-02T19:20:21.970 回答