学习如何使用 IBM® Rational® Software
Architect 和 Rational® Systems Developer 工具将 UML 建模适于开发 C++
应用程序。本文描述了7.0版本支持 C++ 领域建模的特性。在此,假设您正在不断更新模型和代码,并且想要实现 UML 与 C++
之间的对应修改。那么您只需要拥有 UML 的基本知识,了解本文中介绍到的 Rational 软件产品,掌握如何运行转换以及如何应用概要文件和构造类型,就可以达到您的目的。
通过本文的姊妹篇 “使用 Rational Systems Developer
和 Rational Software Architect 进行 C++ 转换的技巧” 了解从 UML 模型生成 C++ 代码的方法与技巧。
本文解释了作为一名 C++ 开发人员,如何在使用统一建模语言 UML 建模的时候,继续使用
C++ 数据结构进行设计。您只需掌握 UML、IBM® Rational® Software Architect
和 IBM® Rational® Systems Developer 的相关基本知识即可。
- 在 IBM Rational Systems Developer 创建一个简单的
UML 模型。
- 将一个 C++ 概要文件应用在模型上,这样,就可以在建模的过程中使用 C++
的数据结构。
- 将 C++ 类型库导入模型,这样,就可以使用 C++ 基本类型。
- 生成代码。
- 在类中添加方法体。
- 另外提供一些小技巧,以便在重复进行转换时保存代码和模型的修改。
UML 概要文件是扩展 UML 的一个标准机制,所以对某些特定领域的建模可以在不增加
UML 负担的情况下进行。UML 的创始人不可能涉足到所有的应用领域,因而,他们明智地提供了扩展机制。
应用 C++ 概要文件
例如,要对某个 C++ 具体的元素建模,比如 struct、union、typedef
等,您需要在 UML 模型上应用 C++ 概要文件。步骤如下:
- 确定您正处于 Modeling 透视图。
- 选中模型,然后单击 Properties 视图。
- 在 Properties view 左侧,从列表中选择 Profiles。
- 单击 Add Profile,在 Select Profile
对话框中 Deployed Profile 下方选择 C++ Transformation (如图1和2所示)。
图1. 应用 C++(CPP)概要文件
图2. 选择 C++ 概要文件
导入 C++ 类型库
UML 提供了一组预定义的类型,有 Boolean、Integer、String
和 UnlimitedNatural。而大多数的编程语言,包括 C++,提供了更为丰富的基本类型。在 C++
中建模的时候,您可能经常需要使用 C++ 预定义的基本类型(比如,将一个类型赋给某个属性、参数、操作返回类型,等)。下面讲述如何导入
C++ 模型库:
- 在 Project Explorer 中右键单击 UML 模型。
- 如图3所示,选择 Import Model Library。
图3. 导入 C++ 类型库
- 如图4所示,在 Import Model Library 的运行界面上,从下拉列表框中选择
C++ Types。
图4. 选择要导入的 C++
类型库
现在已经作好为 C++ 特定元素建模的准备了。请接着参看后面的示例。
创建一个简单的 UML 模型,car factory。
创建如图5所示的 UML 模型。创建的过程如下所示:
- 这个示例模型中,Bus 和 Car 的基类是 Vehicle。
- Bus、Car 和 Vehicle
类被创建在一个名为 Vehicles 的 UML 包中。
- 同样的,在名为 Parts 的包中,建立Engine
和 Wheels 类。
- Car 与 Engine 之间存在组合的关系。
- 理论上, Car 和 Engine 是不可分的,因为汽车需要引擎。
- Car 和 Bus 与 Wheels
都有聚合的关系。
- 本例中,轮胎可以没有汽车而存在,汽车可以没有轮胎而存在 -- 至少在组装的时候。
图5.一个简单的汽车工厂 UML
模型的示例
在模型中创建 C++ 元素
- 接下来,创建一个名为 Strategy 的 UML 包。
- 在 Strategy,定义公共汽车的路线和起点。
- 创建一个名为 Route 的类,用来表示路线;一个名为 Address
的类,用来表示地址,比如公共汽车路线的起点。
- Address 需要是 C++ struct 元素而不是普通的类。
- 为 UML 模型指定每个公共汽车的路线。如图6所示,您可以为 Vehicles
包中的 Bus 类和 Route 类之间设置聚合关系。
- 起始点是路线的一个属性。所以,为 Route 类增加一个类型为 Address,名称为
startingPoint 的属性。
图6. 名为 Strategy UML
包的内容
在图6中,请注意 Address 是 <<cpp_struct>>类。创建的步骤如下:
- 创建一个 UML 类,命名为 Address。
- 将 cpp_struct 原型应用给新建立的类。
- 将一个原型应用给 UML 元素,转到 Properties
视图。
- 如图7所示,从左侧的列表中选择 Stereotypes,然后单击
Apply Stereotypes。
图7. 应用一个原型
- 从该元素可用的原型列表中选择 cpp_struct。同时,也可以留意一下其它的选择,以备日后参考。
您很快就能发现,将这个模型转换成代码的时候,带有<<cpp_struct>>原型的
Address 类将会生成一个 struct 元素,而不是一个类。
在由模型生成 C++ 代码之前,需要通过创建转换配置来设置相应的参数。
创建转换配置
步骤如下:
- 单击 File > New > Others,然后选择
Transformations 文件夹中的 transformation configuration。
- 在 New Transform Configuration 向导中,指定配置文件名,此处命名为
tc1。
- 选择 transformation type 和 project。
- 展开 IBM Rational Transformations
列表,然后选择转换类型 UML to C++。
- 本练习中,使用已有 UML 模型项目来保存转换配置文件。
- 单击 Next,继续进行后面的步骤。
- 在 Source and Target 选项卡中:
- Source:选择 UML 模型。
- Target:创建一个新的 C++ 项目。
- 请确定 source 和 target 都是选中的,然后单击
Finish。
注:
如果需要,您可以再对转换配置进行修改。
生成代码
之后的步骤就比较简单了。
- 进行到现在,您已经完成了大部分比较难的工作,接下来,只需右键单击 tc1.tc,然后从弹出式菜单中选择
Transform > UML to C++,就可以在选定的项目中生成代码。
- 看一下 Route 类生成的代码。如列表1所示,它包括 startingPoint
和 endingPoint 属性,以及 getFare() 方法。
列表1. Route 类生成的代码文件 Route.h
#ifndef ROUTE_H
#define ROUTE_H
//Begin section for file Route.h
//TODO: Add definitions that you want preserved
//End section for file Route.h
struct Address;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
class Route
{
private:
//@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_Hk7qMACuEdy9t-_gdCbefQ"
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
float runningCost;
//@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_hKd58ACuEdy9t-_gdCbefQ"
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
float expectedProfit;
//@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_ieiw8ACuEdy9t-_gdCbefQ"
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
Address * startingPoint;
//@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_jkEOkACuEdy9t-_gdCbefQ"
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
Address * endingPoint;
public:
//@uml.annotationsderived_abstraction="platform:/resource/UML-1/
DWArticle-1.emx#_kawmAACuEdy9t-_gdCbefQ"
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
float getFare()const ;
}; //end Class Route
#endif
|
如列表2所示, getFare 方法的默认内容已经生成。
列表2. Route.cpp
#include "Route.h"
//Begin section for file Route.cpp
//TODO: Add definitions that you want preserved
//End section for file Route.cpp
float Route::getFare() const
{
//TODO Auto-generated method stub
return 0;
}
|
请注意,默认生成的内容一般不能够直接使用,因为 fare 总是 0
(zero),而这并不是一个有利的业务!所以需要将 getFare 方法的内容用列表3来代替。
列表3. Route.cpp
float Route::getFare() const
{
// Calcualte the fare
return runningCost * expectedProfit;
}
|
现在,在UML模型中为 Route 类添加另一个名为 print_disclaimer()
的方法。
- 设置返回类型为 String。
- 请注意,我们已为 getFare 方法添加内容,修改了Route.cpp文件。
- 使用相同的配置 (tc1.tc > Transformation
> UML to C++)运行转换。
- 选择目标文件自动更新(默认选项)。
现在,一起来看看更新的代码(列表4)。
列表4. 更新的 Route.cpp
#include "Route.h"
//Begin section for file Route.cpp
//TODO: Add definitions that you want preserved
//End section for file Route.cpp
float Route::getFare() const
{
// Calcualte the fare
return runningCost * expectedProfit;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
const char * Route::print_disclaimer()
{
//TODO Auto-generated method stub
return 0;
}
|
请注意,修改的 getFare() 方法体已被保存。同时,模型中新添加的 print_disclaimer
方法已在 Route.h 和 Route.cpp 文件中生成新的代码。这样,您可以继续在代码中执行方法,同样地,可以对模型作增量修改。这在模型驱动迭代开发中相当有用的。
print_disclaimer 方法体的代码如图5所示。请注意,我们使用了 cout
操作符,但 C++ 不能够识别。然而,代码是否能够正确解析,这是相当重要的,所以当转换再次执行的时候,应当将代码结构和方法体保存下来。如果想使这段代码可编译,您需要在
cpp 文件中添加 #include <iostream> 和 using namespace std;。当重复执行
UML 与 C++ 转换的时候,这些声明将会被保存下来。把这些声明插入到以下两条注释之间:
//Begin section for file Route.cpp
//End section for file Route.cpp
|
您添加到这个节中的内容将一字不漏地保存下来, 并且不需要 C++ 转换解析。
列表5. Route.cpp
#include "Route.h"
//Begin section for file Route.cpp
#include <iostream>
using namespace std;
//End section for file Route.cpp
float Route::getFare() const
{
// Calcualte the fare
return runningCost * expectedProfit;
}
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
const char * Route::print_disclaimer()
{
const char *s = "No Refund once the ticket is purchased\n";
cout << s;
return s;
}
|
下载:
- UML 模型和 C++ 项目示例:选择 File > Import,然后按照
Import Existing Projects into Workspace 向导的提示操作,就可以将项目导入到
Eclipse 工作空间。
本文讲述了使用 Rational Systems Developer 创建 UML
model,然后生成 C++ 代码的基本步骤,以及保持代码与模型同步的方法。想要了解更多的信息,请参阅相关的链接资源。
描述 |
名字 |
大小 |
下载方法 |
Sample UML
Model project. |
MyAutomobileFleet.zip |
7KB |
|
Final CPP
Project |
AutomobileFleetCode.zip |
33KB |
|
学习
获得产品和技术
讨论
|