我们尝试建模什么?
Derived 和 Base 之间的 C++ 泛化同时做了两件事:
- 它绑定
Base模板类的参数,
- 它创建了通过绑定参数获得的类之间的泛化。
对于不熟悉 C++ 的人,让我们通过别名来说明这一点:
template<typename TB1, typename TB2, typename TB3>
class Base { };
template<typename TD1, typename TD2>
class Derived : public Base<TD1, TD2, int> { };
int main() {
using MyDerived = Derived<string, Test>; // class corresponding to binding parameters
using MyBase = Base<string, Test, int>;
MyBase *p = new MyDerived(); // this assignment works because the bound
// MyBase generalization is a generalization
// from MyDerived
}
所以这段代码意味着Base 到Derived 的通用特化是真的,无论参数绑定如何,特别是绑定MyBase 和MyDerived。
如何在 UML 中显示它?
第一次尝试可能是简单地使用绑定:
UML 规范,第 9.3.3.1 节: (...) 内容如何合并到绑定元素中的细节保持开放。 (...) 绑定的分类器可能具有除其绑定产生的内容之外的内容。
这意味着Derived 是一个绑定分类器,它通过绑定Base 的参数并添加“自己的内容”,包括对基本元素的重新定义(“覆盖”)。但这并不能恰当地反映从Derived 获得的绑定类和直接从Base 获得的绑定类之间也存在继承。
更好的方法是在模板之间使用继承,这对应于 C++ 语义:
图片1
这显示了继承。但是UML部分9.9.3.2 模板分类器特化说:
RedefinableTemplateSignature 重新定义所有作为模板的父分类器的 RedefinableTemplateSignatures。扩展(重新定义)签名的所有正式 TemplateParameters 都包含为扩展签名的正式 TemplateParameters,以及为扩展签名本地指定的任何 TemplateParameters。
我理解这意味着模板参数增加(即集合将是 TB1、TB2、TB3、TD1 和 TD2),并且没有预见到定义某些父元素的本地绑定的语义或符号。
因此,最干净的方法是分解绑定和继承:
图片2