C/C++函数指针的UML表示

πάν*_*ῥεῖ 17 c c++ uml enterprise-architect

在UML结构图中,C/C++函数指针(fp)的最佳表示是什么?

我正在考虑使用一个接口元素,即使是"退化",但最多只能声明一个操作.

我在本文档中找到了一些建议:C和UML同步用户指南,第5.7.4节.但这听起来很麻烦,在实践中并不是很有用.即使从非常低级别的语义视图来看也是如此.这是一个简要显示其概念的图表: 在此输入图像描述

恕我直言C和C++函数指针被用作界面的狭窄视图,它只提供单个函数及其签名.在C fp中,它还将用于实现更复杂的接口,声明包含一组函数指针的结构.

我想我甚至可以设法让我的特定UML工具(Enterprise Architect)转发生成正确的代码,并同步代码更改而不会造成伤害.

我的问题是:

  1. 声明fp作为UML中界面元素的一部分会提供正确的语义视图吗?
  2. 单个fp声明应该使用什么样的刻板印象?至少我需要在代码中提供一个typedef,所以这将是我的胆量选择.(我发现这个构造型是Enterprise Architect专有的)我需要定义一个合适的构造型来使代码生成适应.实际上我选择了刻板印象的名称'委托',这是否有任何影响或语义冲突?
  3. 至于C++,是否会在类元素中嵌套一个'委托'的类型化接口,足以正确表达一个类成员函数指针?

这是我对C语言表示的想法示例图: C语言接口和函数指针实现

这是应该从上面的模型生成的C代码:

struct Interface1;

typedef int (*CallbackFunc)(struct Interface1*);

typedef struct Interface1
{
    typedef void (*func1Ptr)(struct Interface1*, int, char*);
    typedef int (*func2Ptr)(struct Interface1*, char*);
    typedef int (*func3Ptr)(struct Interface1*, CallbackFunc);

    func1Ptr func1;
    func2Ptr func2;
    func3Ptr func3;

    void* instance;
};

/* The following extern declarations are only dummies to satisfy code
 * reverse engineering, and never should be called.
 */
extern void func1(struct Interface1* self, int p1, char* p2) = 0;
extern int func2(struct Interface1* self, char*) = 0;
extern int func3(struct Interface1* self, CallbackFunc p1) = 0;
Run Code Online (Sandbox Code Playgroud)

编辑:
整个问题归结为手头的UML工具及其特定的代码工程功能的最佳方式.因此,我添加了标签.

Uff*_*ffe 9

关于函数指针的主题,EA的帮助文件有如下说明:

导入C++源代码时,Enterprise Architect会忽略函数指针声明.要将它们导入模型,您可以创建一个typedef来定义函数指针类型,然后使用该类型声明函数指针.以这种方式声明的函数指针将作为函数指针类型的属性导入.

注意"可以." 这是来自C++部分,C部分根本没有提到函数指针.因此,它们得不到很好的支持,而这当然是由于建模和编程社区之间的差距:UML中根本不支持非平凡的语言概念,因此任何解决方案都必须是特定于工具的.

我的建议有点牵扯,它有点hacky,但我认为它应该工作得很好.

因为在UML操作中不是第一类并且不能用作数据类型,我的响应是为它们创建第一类实体 - 换句话说,将函数指针类型定义为类.

这些类有两个目的:类名将反映函数的类型签名,以使程序员在图中看起来很熟悉,而一组标记值将表示用于代码生成的实际参数和返回类型.

0)您可能需要为步骤1-4设置MDG技术.

1)使用Detail"Type = RefGUID; Values = Class;"定义标记值类型"retval".

2)使用名为"par1","par2"的相同Detail定义另一组标记值类型,依此类推.

3)使用包含"retval"标记值(但没有"par"标记)的类构造型"funptr"定义一个配置文件.

4)修改代码生成脚本属性声明和参数以检索"retval"(总是)和"par1" - "parN"(定义的位置)并为它们生成正确的语法.这将是棘手的一点,我实际上没有这样做.我认为可以毫不费力地完成,但你必须尝试一下.您还应该确保没有为"funptr"类定义生成代码,因为它们代表匿名类型,而不是typedef.

5)在目标项目中,定义一组类来表示原始C类型.

有了这个,你可以将一个函数指针类型定义为一个名为"long(*)(char)"的«funptr»类,用于获取char并返回long的函数.

在"retval"标签中,选择您在步骤4中定义的"long"类.

手动添加"par1"标签,并选择上面的"char"类.

您现在可以将此类用作属性或参数的类型,或EA允许类引用的任何其他位置(例如,在其他«funptr»类的"par1"标记中;这使您可以轻松地创建指针类型函数,其中一个参数本身是函数指针类型).

这里最讨厌的是编号为"par1" - "parN"的标签.虽然在EA中可以定义几个具有相同名称的标签(您可能需要更改标记值窗口选项以查看它们),但我认为您不能在代码生成脚本中检索不同的值(即使你可以不认为订单必然会被保留,参数顺序在C)中很重要.因此,您需要事先确定最大参数数量.在实践中不是一个大问题; 设置说20个参数应该是充足的.

此方法对逆向工程没有帮助,因为EA 9不允许您自定义逆向工程过程.然而,即将到来的EA 10(目前在RC 1中)将允许这一点,虽然我自己没有看过它,所以我不知道这将采取什么形式.

在此输入图像描述