C++:根据预处理器指令,用两种不同的可能类型表示 class 图中的变量

C++: Represent variable in class diagram with two different possible types depending on preprocessor directive

我有一个 class,它使用一个变量,根据预处理器指令 (#ifdef #else #endif),该变量可以有两种不同的类型。我应该如何在不创建另一个 UML class 图的情况下清楚地表示此变量的类型?

预处理器技巧与 OOP 设计

您使用预处理器以类似于此示例的方式影响您的 class 定义:

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++ 实现来实现这种设计。

对于 class 专业化 (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
    ...
};

这非常强大,允许在 run-time 以(非常)小的性能开销做出决定。但是预处理器是编译时间,还有一个强大的 compile-time 解决方案以及模板:

template <class U> 
class TA {
    U myvar; 
    ...
}; 

然后您可以在代码中用正确的类型实例化 class:

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,y,z;