内容


使用 Rational Systems Developer 或 Rational Software Architect 进行 C++ 转换的提示和技巧,第 1 部分

控制由 UML 模型生成的 C++ 代码

Comments

系列内容:

此内容是该系列 # 部分中的第 # 部分: 使用 Rational Systems Developer 或 Rational Software Architect 进行 C++ 转换的提示和技巧,第 1 部分

敬请期待该系列的后续内容。

此内容是该系列的一部分:使用 Rational Systems Developer 或 Rational Software Architect 进行 C++ 转换的提示和技巧,第 1 部分

敬请期待该系列的后续内容。

应用 C++ Transformation 概要文件以实现 C++ 结构的建模。

在统一建模语言 UML 和某特定领域之间建立联系的标准方法是使用 UML Profile(UML 概要文件)。UML 概要文件可以为已有 UML 元素定义附加语义和特性,例如类、操作等。建模 C++ 特定元素的时候,如 结构体、联合体、名字空间 等,需要用到 UML 概要文件。在 Rational Software Architect 和 Rational Systems Developer 使用 C++ Transformation profile 实现 UML 向 C++ 的转换,这个概要文件在 UML 模型中的应用如下所示。

  1. 在 Project Explorer 中选择概要文件将要应用的 UML 模型。
  2. 在 Project Explorer 保持模型是选中状态,转换到 Properties View,单击 Profiles 选项卡。
  3. 如图1所示,单击 Add Profile 按钮。
图1. 将 UML 运用到 C++ Transformation 概要文件
Applying the UML to C++ Transformation profile
Applying the UML to C++ Transformation profile
  1. 如图2所示,从 Deployed Profile 下拉列表框中选择 C++ Transformation
图2. 选择 C++ Transformation
Sample UML2 Model
Sample UML2 Model

导入 C++ 类型库

UML 提供了一组已定义好的类型,有 Boolean, Integer, StringUnlimitedNatural。而大多数的编程语言,包括 C++,提供了更为丰富的基本类型。在 C++ 中建模的时候,您可能经常需要使用 C++ 预定义的原始类型(比如,将一个类型赋给某个属性、参数、操作返回类型,等)。To import the C++ model library that is shipped with the C++ Transform,在 Project Explorer 中右键单击UML模型,然后选择 Import Model Library,如下图3所示。

图3. 导入 C++ 类型库
Importing the C++ Type Library using the pop-up menu
Importing the C++ Type Library using the pop-up menu

如图4所示,从 Deployed Library 列表中选择 C++ Types

图4. 导入 C++ Type Library
Importing the C++ Type Library
Importing the C++ Type Library

在模型中创建 C++ 名字空间

本章节讲述如何在 UML 模型中为 C++ 名字空间建模。在 C++ 中创建一个名字空间时,需要将 cpp_namespace 原型应用在 UML 包。在 UML 向 C++ 转换的过程中,一个 UML 包默认被映射成一个文件夹。如果想要将 UML 包映射成名字空间,而不是文件夹,那么,您需要应用 cpp_namespace 原型,然后设置 NamespaceName 的属性,使其与指定的名字空间相关联。这个 stereotyped UML 包下所有的 类、结构、枚举 (以及其它)生成代码之后,都将包括在这个名字空间中。

您可能想知道为什么名字空间不能直接采用 stereotyped 包的名称。这是为了支持 C++ 匿名的名字空间建模。所以,如果您将 NamespaceName 属性设置为空,那么,该名字空间就会被认为是匿名的。

建模 C++ typedefs

要建模 C++ typedef,需要创建一个 UML 类并在其上应用 cpp_typdef 原型。该原型提供了以下属性/值:

  • arrayDimensions
  • ImplementationType
  • qualifier

想要创建一个类型定义,比如 typedef int const IntMatrix100_20_t [10][20];,首先创建一个 UML 类 IntMatrix100_20_t,然后应用 cpp_typedef 原型。如图5所示,设置该原型的属性。

图5. 建立一个 C++ 类型定义
C++ Typedef properties
C++ Typedef properties

在将 typedef 定义与概要文件中提供的属性相关联的过程中,您可能会考虑到以下方式: typedef <ImplementationType> <qualifier> <Class Name> <arrayDimensions>

创建多维数组属性

在本节中,您将会学到如何为一个大小为[10][20][30]的三维数组定义属性。在 Project Explorer 中选择需要赋给多维数组的属性。在 Properties 视图中,单击 Stereotypes 选项卡,然后单击 Apply Stereotypes 按钮,并选择 cpp_type 原型。这个原型提供了以下属性/值:

  • arrayDimensions
  • InitializerKind
  • isAuto
  • isMutable
  • isRegister
  • isVolatile
  • qualifier

如图6所示,在 arrayDimensions Value 处,指定 [10][20][30]。这样,在源代码中就会生成维度属性为[10][20][30]的数组。

图6. 设置 Multidimensional Attributes
Setting Mutidimensional Attributes
Setting Mutidimensional Attributes

将一个方法的形参设置为常量

这个技巧的原理同上(前面提到的定义多维数组)。在 Project Explorer 中选择准备设置为 const 的参数。单击 Apply Stereotypes 按钮并选择 cpp_type 原型。该类型提供了以下属性/值:

  • arrayDimensions
  • InitializerKind
  • isAuto
  • isMutable
  • isRegister
  • isVolatile
  • qualifier

这些属性都是可能用得到的,但暂时只介绍 qualifier 属性。在 qualifierValue 处,输入 const (如 图5 所示)。这样,当转换执行的时候,将在源代码中为选定的参数生成带有常量修饰符的函数签名。

注: 请确保输入的值是有效的。如果输入错误,则会导致编译失败,您需要在再次运行转换之前修正错误。

另外,cpp_type 原型也适用于类的属性。但是,生成一个常量属性的更简单的方法是将属性标明为 Read Only

将整个方法声明为常量

假设您想要将一个方法声明为常量,以便在生成的代码中带有 const 关键字: )int Operation1(MyType Parameter1 const;。您需要在 Properties 视图的 General 选项卡中选择 Query 修饰符。这里,不需要应用原型。

图7. 创建一个常量方法
C++ Const Method
C++ Const Method

给一个方法增加异常处理

Exceptions 是 UML 中重要的类,它在建模过程中不需要使用概要文件。为了简化并推广建模, UML to C++ Transformation 使用了普遍适用的 UML 属性,而不是概要文件。要生成一个 throw 子句,比如 int Operation1() throw ( MyType);,您首先需要为操作创建一个参数,然后设置其 Is Exception 属性为 true

在转换过程中,参数名是可以被忽略的,但最好还是定义一个合适的名称(以备异常抛出时正确提示)。图8显示了如何将参数的 Is Exception 属性设置为 true

图8. 设置某方法的 throw 类型
Throw Clause for Method
Throw Clause for Method

控制生成的代码中的 include 声明

UML to C++ Transformation 可以自动生成恰当的 include 声明。 然而,您可能想要根据需要生成更合适的 include 声明。例如,已确定要使用本地方法体的某个类型变量,因此,想要生成包括在文件中的 include 声明建模时,您可能需要创建两个类之间的依赖,然后将 cpp_dependency 原型应用在依赖。这个原型和名为 IsInclusionInHeader 的属性一起出现,该属性值默认为 false。如果需要将 include 声明包括在生成的文件体中,请将这个属性值设为 false;如果需要将 include 声明生成在头文件中,那么,可以不设置依赖的 cpp_dependency 原型,也可以应用原型并将 IsInclusionInHeader 属性值设为 true

使用文件级别得重用保护部分

如果要使用标准库的类型,或者一些源代码的其它库,您需要在模型中将这些类型设置为普通的字符串。例如,如果要将一个属性声明为整型,您需要在模型中指定它的类型为 vector<int> 转换时,将会把这些类型当成原始类型,并且不会生成任何 include 声明或其它声明。因此,您需要将这些都明确地包含进源文件中。

比如,对于 vector 类型,您应当明确地将 include 声明放置在源代码中,比如 #include <vector>。如列表1所示,在应用 UML 向 C++ 的转换过程中,每个生成的文件都一字不漏地包含一些段落的内容。请注意 //TODO: Add definitions that you want preserved。您添加到 Begin sectionEnd section 中的任何内容都将被保存下来。请在此处添加声明,比如这里的 #include <vector>

列表1. 类 Car 所生成代码
#ifndef CLASS1_H
#define CLASS1_H
//Begin section for file Class1.h
//TODO: Add definitions that you want preserved
//End section for file Class1.h

#include "MyType.h"

//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
class Class1
{

    //Begin section for Class1
    //TODO: Add attributes that you want preserved
    //End section for Class1
    public:

        //@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
        int Operation1()const  throw ( MyType);

};  //end Class Class1

#endif

删除类级别得重用保护部分

请注意,在前面列表1的代码中,有一段 //Begin section for Class1 ... //End section for Class1 ,您可以将 C++ 中所有不能建模的声明保存在这里。返回 UML to C++ Transformation 时,不会覆盖这段声明。如果您不需要这一声明出现在生成的代码中,可以选择删除。但是,删除之后,即使再次运行 UML to C++ Transformation,这些声明也不会重新生成。

如果不需要,可以删除如列表2所示的段落,那么删除之后不能够重新生成。假使想要恢复这些声明,您就需要手动地进行插入。

列表2. 类 Car 生成的代码
    ...
    //Begin section for Class1
    //TODO: Add attributes that you want preserved
    //End section for Class1
    ...

不修改 UML 模型的情况下,改变生成包的名称。

要改变包的名称,请双击打开转换配置文件。如图9所示,单击 Mapping 选项卡,选择 Enable mapping

图9. 使用映射模型
Enable Mapping Model
Enable Mapping Model

单击 New 按钮,创建一个默认的映射模型,赋给一个适合的名称。单击 Edit Mapping 按钮,出现如图10所示的对话框。

图10. 编辑映射模型
Edit Mapping Model
Edit Mapping Model

假使您正进行到如图11所示的 UML 模型。如果没有映射模型,那么 Date 类将会生成在一个名为 Package1 的文件夹内。然而,如果您想要将 Package1 生成为 Folder1,那么需要使用映射模型。浏览映射模型,找到 Package1,然后在向导底端的 Mapped Name 编辑框输入 Folder1。这样,在生成的代码中,Date 类就生成在名为 Folder1 的文件夹内了。

图11. 您正在操作的 UML 模型
Mapping UML Model

在同一个文件里生成多个类。

在映射模型中,假如您想将一个 UML 类映射为另外的名称,您需要改变其将要生成文件的名称,而不是类名。默认情况下,顶级类将生成一个与类名相同名称的文件。因此,对于一个名为 MyClass 的 UML 类,UML 向 C++ 的转换将会生成文件 MyClass.h 和 MyClass.cpp。

但是,在使用映射模型的时候,您也可以选择生成与原类名不同名称的文件。比如,您可以改变 UML 包的名称,生成另外命名的文件夹;您也可以将一个 UML 类映射为另外命名的文件。类的名称并不受映射模型的影响。因此,要想在一个文件中生成多个类,您所需要做的仅仅是在映射模型中为它们指定相同的目标名称。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Rational
ArticleID=248260
ArticleTitle=使用 Rational Systems Developer 或 Rational Software Architect 进行 C++ 转换的提示和技巧,第 1 部分: 控制由 UML 模型生成的 C++ 代码
publish-date=08132007