为什么*一切*在ATL / WTL中使用模板基类
Why does *everything* use a template base class in ATL/WTL?
我在理解 ATL/WTL 代码中模板的用途时遇到了很多麻烦。
当您查看 WTL 时,您会看到如下代码:
template <class TBase>
class CEditT : public TBase
{
...
};
typedef CEditT<ATL::CWindow> CEdit;
为什么使用模板基类定义CEditT
?
换句话说,在什么情况下CEditT<T>
会在T
不CWindow
的情况下被实例化?
您就可以重写 ATL/WTL 类调用的ATL::CWindow
中的方法。 如果在ATL::CWindow
中有一些你不喜欢的东西,你可以使用重写的方法从ATL::CWindow
派生一个类,然后将你的新类作为TBase
传递。
例如,ATL::CWindow::CenterWindow
很长一段时间以来都有一个错误,它没有正确考虑多个监视器,我已经看到人们使用这种技术通过固定的实现覆盖CenterWindow
。
假设使用组合代替:
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
,这可能是有用的。此外,它将可以访问ITEM
的任何protected:
部分。
这样它就可以利用奇怪的重复模板模式。如果创建派生类CEditT
则定义将class CMyEdit : public CEditT<CMyEdit>
。通过静态地将其this
指针强制转换为类,CEditT
可以调用您的方法,而无需使用 vtable。
为什么一切都在 ATL/WTL 中使用模板基类?
简而言之,要通过设计模式(而不是C++习语)实现"奇怪的编译时多态性形式",人们可以称为"颠倒继承"作为"指定基类的基类"的技术,以便"允许您将自己的类插入类层次结构"以实现专用类型的灵活性"而无需对任何特定的派生类进行硬编码实现"。
在阅读了由 Jim Beveridge 撰写并由 Visual C++ Developers Journal 于 1999 年 7 月发表的优秀文章 ATL 和颠倒继承 - 了解 ATL 的非典型设计方法后,这一切都应该变得清晰起来。这是指向同一篇文章的完整非分页副本的链接(也在 Wayback Machine 中)。
- std::具有相同基类的类的变体
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 基类中的函数名称解析
- C++初始化基类
- 如何通过派生类函数更改基类中的向量
- 如何定义一个纯抽象基类
- 如何使用基类指针引用派生类成员
- 继承:构造函数,初始化C++11中基类的类C数组成员
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何引用基类的派生类?
- 如果基类包含双指针成员,则派生类的构造函数
- 在模板基类中为继承类中的可选重写生成虚拟方法
- 为什么此派生对象无法访问基类的后递减方法?
- 公开最直接的基类模板名称
- 当基类是依赖类型时,这是一个缺陷吗
- 如何使基类的运算符对基类的可变参数数可见(请参阅下面的代码)?
- 模板基类中的静态变量
- C++ 继承:将子类传递给需要基类的函数并获取子类行为
- 为什么*一切*在ATL / WTL中使用模板基类