问题描述
我有一个类,该类使用一个变量,根据预处理器指令(#ifdef #else #endif),变量可以具有两种不同的类型。我应该如何干净地表示此变量的类型而不创建另一个UML类图?
解决方法
预处理器技巧与OOP设计
您可以使用预处理器以类似于此示例的方式影响类定义:
class A {
#ifdef X
V myvar;
#else
W mywar;
#endif
...
};
此技巧使用预处理器并使用令牌替换,而不是使用适当的OOP设计来实现相同的结果。
问题的UML方面
UML不知道预处理器,也没有提供很多技巧。在UML中,您需要为等效的OOP构造建模以表达您想要做的事情。可以考虑两个主要方向:
- 您将为generalization U特长V和W建模。还将A与U的关联建模。这将涵盖您的设计,尽管它更灵活,因为它允许在以下位置选择U运行时。
- 如果使用带接口的语言,通常会在接口中定义U,而V和W将显示
«realization»
dependency(带三角形箭头的虚线)。 - 您将使用UML templates和参数化类型U的绑定为模板建模。
最后一个选项与预处理器最接近,因为它是编译时间。
有关预处理器的C ++替代方法的更多信息
在C ++或其他OOP语言中,可以使用与上述UML构造相对应的C ++实现来实现这种设计。
对于类专业化(C ++),您将具有以下内容:
class U {...}; // a more general type that covers some specializations
class V:public U {...};
class W:public U {...};
class A {
U myvar; // ???
...
};
不幸的是,由于C ++对象模型和切片的值语义,这通常不能很好地工作。因此,要使其正常工作,您需要参考,指针或对smart_pointer进行操作,例如:
class A {
unique_ptr<U> myvar; // smart pointer initialized in construtctor or intejected
...
};
这是非常强大的功能,并且允许在运行时进行决定(非常少的性能开销)。但是预处理器是编译时,并且模板还有一个强大的编译时解决方案:
template <class U>
class TA {
U myvar;
...
};
然后您可以在代码中使用正确的类型实例化该类:
class TA<V> x,y,z;
class TA<W> a,b,c;
class TA<int> d,e,f; // no need to have a subtype relation
您甚至可以使用以下类型的别名使代码更具可读性:
using A = class TA<V>; // instead of #define X
A x,z;