这将是一个C / C ++函数指针(FP)的UML结构图中最佳表示?
我在考虑使用界面元素,可能是即使“堕落”与大多数单次操作具有约束声明。
我发现了一些建议,本文件中: C和UML同步用户指南,第5.7.4节 。 但是,这听起来相当繁琐,在实践中不是非常有用。 即使直接从语义视图的一个非常低的水平。 下面是简要地展示了他们的概念图:
IMHO在C和C ++函数指针被用作其中仅提供了一个单一功能的接口的这种变窄视图和它的签名。 在C FP的将也可以用来实现更复杂的界面声明包含了一组函数指针的结构。
我想,我甚至可以设法让我特别的UML工具(企业架构师)转发生成正确的代码,并与无伤害代码更改同步。
我的问题是:
- 将FP的声明作为UML界面元素的一部分proivde正确的语义看法?
- 应使用单FP声明什么样的刻板印象? 至少我需要在代码中提供一个typedef
所以这将是我的胆量的选择。 (我发现这个刻板印象是私有企业架构师),我需要定义一个适当的刻板印象,以获得代码生成适应。 其实我已经选择了刻板名“代理”,这是否有任何影响或语义冲突? - 至于C ++,将嵌套一个“委托”的一类元件sterotyped接口有足够的正确表达一个类的成员函数指针?
下面是我的想法对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;
编辑:
整个问题归结什么是手头的UML工具及其特定代码的工程能力的最佳途径。 因此,我已经添加了企业架构师标签。
EA的帮助文件有以下对函数指针的主题说:
当导入C ++源代码,企业架构师忽略函数指针声明。 为了将其导入到你的模型,你可以创建一个typedef定义一个函数指针类型,然后声明使用该类型的函数指针。 以这种方式声明的函数指针被导入为函数指针类型的属性。
注意:“可以。” 这是从C ++部分,C部分并没有提到函数指针的。 所以,他们不能很好的支持,这又是当然的,由于建模和编程界之间的差距:非平凡的语言概念根本就不在UML的支持,所以任何解决方案将必然是工具特定的。
我的建议是参与了一下,这是一个有点哈克,但我认为它应该工作得很好。
由于UML操作是不是一流的,不能用作数据类型,我的回应是创建一流的实体为他们 - 换句话说,定义函数指针类型为类。
这些课程将有两个目的:类名称将反映函数的类型签名,从而使它看起来很熟悉,以图中的程序员,而一组标签值将代表实际的参数和代码生成使用返回类型。
0)你可能想建立一个千年发展目标的技术步骤1-4。
1)定义一个标记的值类型“RETVAL”与明细“类型= REFGUID;值=类;”
2)定义的另一组标记值类型与名为“PAR1”相同的详细信息,“PAR2”等。
3)定义与一类构造型“funptr”含有“RETVAL”标记值(但没有“相提并论”标记的轮廓)。
4)修改代码生成脚本属性声明和参数检索“RETVAL”(始终)和“PAR1” - “PARN”(这里所定义的),并为他们正确的语法。 这将是棘手的一点,我并没有真正做到这一点。 我认为它可以没有太多的精力来完成,但你也来试试吧。 你还应该确保没有代码为“funptr”类定义生成的,因为它们代表匿名类型,而不是类型定义。
5)在您的目标项目,定义了一组类来表示原始的C类型。
有了这个,你可以定义一个函数指针类型为«funptr»类像“长(*)(字符)”的,需要一个字符,并返回一个长函数的名称。
在“RETVAL”标签,选择在步骤4中定义的“长”级。
手动添加“PAR1”标签,并选择“字符”级如上。
现在你可以使用这个类作为一个属性或参数,或任何其他地方,其中EA允许类引用(比如在不同的«funptr»类的“PAR1”标签的类型;这使您可以轻松地创建的指针类型功能,其中的参数之一是一个函数指针类型的本身)。
这里的hackiest位是编号为“PAR1” - “PARN”标签。 虽然可以在EA定义具有相同名称的几个标签(您可能需要更改标记值窗口选项查看),我不认为你可以检索代码生成脚本不同的值(即使你能我不认为为了必然会被保留,并且参数顺序是在C语言很重要)。 所以,你需要事先确定的参数最大数量。 在实践中没有一个巨大的问题; 建立说20个参数应该是充足的。
这种方法是没有帮助的逆向工程,如EA 9不允许您自定义逆向工程过程。 然而,即将到来的EA 10(RC 1目前)将允许这一点,虽然我还没有自己看着它,所以我不知道什么样的形式,这将需要。
函数指针的定义是出于UML规范的范围。 更重要的是,它是不是由许多UML建模软件支持的特定语言的功能。 所以,我觉得一般回答你第一个问题,建议避免此功能。 您提供的技巧是相关的只有企业架构师,并且不与其他UML建模工具兼容。 下面是函数指针是如何在其他一些UML软件支持:
MagicDraw UML使用<< C++FunctionPtr
>>定型为FP类成员和<< C++FunctionSignature
>>为函数原型。
的代码示例(取自官方网站 -见“造型的typedef和函数指针的C ++代码生成”的Viewlet):
class Pointer
{
void (f*) ( int i );
}
相应的UML模型:
Objecteering限定FP与对应C ++ TypeExpr音符属性。
从IBM Rational Software Architect中不支持函数指针。 用户可能在被期间代码 - > UML和UML的>代码转换阔叶不变用户定义段将它们添加到生成的代码。
似乎是正确的我。 我不知道,你应该潜入descripting您的单一函数指针的类型和关系的低层细节。 我通常会发现描述的界面,而不需要分解它的内部元件足够detalization。
我想你可以几乎包住函数指针带班。 我认为UML不必是蓝图级别的代码,记录的概念更重要。
我的感觉是,你的愿望映射UML接口的结构与 - 函数指针Ç成语。
接口1是模型中的重要元素。 声明函数指针的对象类型所有的地方会让你的图表难以辨认。
企业架构师,您可以指定自己的代码生成器。 认准代码模板框架 。 你应该能够用新的刻板印象或两个的帮助下修改既有代码生成器对C。
就像你的第一个例子,我会用一个分类,但它隐藏掉在配置文件中。 我认为他们已经包括它的解释这个概念的清晰度; 但在实践中定型的整体思路是抽象掉的细节到配置文件,以避免“噪音”问题。 EA是处理配置文件相当不错。
当我从你的第一个例子不同的是,我会分类基本类型刻板印象不是数据类型的刻板印象。 数据类型是域范围对象,而原语类型是具有限定出侧UML的范围语义的原子元素。 这并不是说你不能添加注释,尤其是在配置文件或给它一个非常明确的刻板印象的名字一样functionPointer。
我已经能够获得与企业架构师工作的东西排序。 它有点哈克的解决方案,但它符合我的需要。 我做了什么:
创建一个名为FuncPtr一个新类的刻板印象。 我跟着指南这里: http://www.sparxsystems.com/enterprise_architect_user_guide/10/extending_uml_models/addingelementsandmetaclass.html当我做这个我做了概要文件的新观点。 所以,我可以把它包含我的主要项目之外。
修改的类代码模板。 基本上,选择C语言,并开始与模板类,并击中了“添加新的原型覆盖”和FuncPtr添加为新的替换。
添加以下代码到新的模板:
%PI="\n"% %ClassNotes% typedef %classTag:"returnType"% (*%className%)( %list="Attribute" @separator=",\n" @indent=" "% );
修改属性声明代码模板。 像以前同样的方式,在一个新的原型添加
添加以下代码到新模板:
%PI = “” %%attConst == “T”? “常量”: “” %
%attType%
%attContainment == “按引用”? “*”: “” %
%attName%
这一切都让我不得不做的就是函数指针在企业架构师的地方。 当我要定义一个函数指针我刚:
- 创建一个普通班
- 添加的标签“返回类型”与我想要的回报的类型
- 在添加的参数属性。
这样,它会创建一个新的类型,可以被包括在其他类属性或参数(构筑物),和运营商。 我没有让运营商本身,因为那就不是被工具作为一种类型,你可以选择内部参考。
因此,它有点哈克,使用特殊的原型类的类型定义,函数指针。