级别: 中级 Vinod V. Uddaraju, 高级软件工程师,
IBM
Pratima Gangalavoi, 系统软件工程师,
IBM
2008 年 10 月 24 日 这篇文章(这个系列的第 3 部分)为您提供了一些技巧可以使您更好地理解如何利用 UML 建模 C++ 特定模型,从而当您在 IBM®Rational®Software Architect 或者 IBM ®Rational® Systems Developer 中为 C++ 转换运行 UML 时产生代码。
这篇文章将向您显示如何建模数组、联合体、抽象类,为属性建模默认值等等。它还为您提供一些关于如何利用 Rational Software Architect 特性来进一步制定由 C++ 转换产生代码的技巧。
利用维数可变的 C++ 建模数组
这个部分讨论了利用 C++ 建模数组的问题,并且它的维数可以像变量一样被指定。要创建一个类型为 a[m] 的一维数组(这里的 m 是一个已经被定义和初始化的整数变量),可以在 UML 模型中在这个数组变量 a 上运行 cpp_type 原型。接下来,将这个原型的数组维度属性设置为 [m],如图 1所示。要完成这个操作,可以按照下面这些步骤进行:
- 选择要被建模成为一个数组的 UML 类属性。
- 由于这个属性在 Project Explorer 中仍然被选择,可以切换到 Properties 视图,然后点击 Stereotypes 页签。
- 点击 Apply Stereotypes 按钮并选择 cpp_type 模型。
- 选择这个模型中具体指定的arrayDimensions属性,然后指定这个数组的维度,如图 1所示。
图 1. 为这个数组确定维度
产生的相关代码显示在列表 1中。
列表 1. 在 Class1 中为这个数组属性产生代码
#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
//@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
private:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
int m;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
int attribute_int_array[m];
public:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
Class1();
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
~Class1();
}; //end class Class1
#endif
|
建模构造函数、分析构造函数,以及拷贝构造函数
这个部分讨论了为一个 C++ 类建模构造函数,分析构造函数,以及拷贝构造函数。要为一个叫作 Class1 的 C++ 类产生这些,可以按照一下步骤进行:
- 创建一个叫作 Class1 的 UML 类。
- 切换到 UML 的 Properties 页签到达 C++ Transformation 配置向导,然后选择 Constructor,Destructor, 以及 Copy Constructor 选项,如图 2所示。
图 2. 建模构造函数、分析构造函数,以及拷贝构造函数
产生的相关代码显示在列表 2中。
列表 2. 由构造函数、分析构造函数,以及拷贝构造函数产生的代码
#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
//@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)"
Class1();
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
Class1(Class1 & arg);
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
~Class1();
}; //end class Class1
#endif
|
建模 Assignment Operator
这部分讨论的是为 C++ 类建模一个赋值操作符。要为 一个叫作 Class1 的 C++ 类产生任务分配器,可以按照一下这些步骤进行:
- 创建一个名为 Class1 的 UML 类
- 切换到 Transformation Configuration 向导的 Properties 页签,并选择 Assignment 选项。
图 3. 为属性建模赋值操作符
产生的相关代码显示在列表 3中。
列表 3. 生成的代码带有激活的赋值操作符
Source File:
#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
//@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)"
void operator =(const Class1 & arg);
}; //end class Class1
#endif
Body File:
#include "Class1.h"
//Begin section for file Class1.cpp
//TODO: Add definitions that you want preserved
//End section for file Class1.cpp
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void Class1::operator =(const Class1 & arg)
{
//TODO Auto-generated method stub
}
|
建模抽象的属性
这个部分讨论的是在 C++ 类中为一个属性建模抽象的属性。要在一个名为 Class1 的 C++ 类中为一个 C++ 属性产生这些,可以按照以下步骤进行:
- 创建一个名为 Class1 的 UML 类。
- 添加一个名称为属性1的 UML 属性,并将它的类型设定为 Integer。
- 然后在 Transformation Configuration 向导的 Properties 页签中选择 Getters and setters 选项。
- 这个转换配置为您提供了更深一层的选项,从而使这些抽象的属性 Inline 或者 By reference,通过选择Getters and setters 下转换配置中的属性来进行,如图 4所示。
图 4. 为属性建模抽象的属性
产生的相关代码显示在列表 4 (Inline) 和列表 5中 (仅供参考)。
列表 4. 产生的代码有 Getters and setters 和 Inline 选项
#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
//@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
private:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
int attribute1;
public:
//get attribute1
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
inline int get_attribute1();
//set attribute1
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
inline void set_attribute1(int attribute1);
}; //end class Class1
#endif
|
列表 5. 产生的代码有带有 By 参数选项的 Getters and setters
#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
//@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
private:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
int attribute1;
public:
//get attribute1
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
int & get_attribute1();
//set attribute1
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
void set_attribute1(int & attribute1);
}; //end class Class1
#endif
|
为 C++ 建模继承
继承在面向对象编程中是一个重要的特性,UML 为它的建模提供了方法。要建模继承,可以利用由 UML 建模面板提供的一般化关系,它是从继承类到基础类而绘制出来的。例如,仔细考虑建模一个拥有多个继承特征的模型。在图 5所示的模型中,来自常见类的 UML 类 DerivedClass1 叫作 BaseClass。
图 5. 为 C++ 建模继承特性
产生的相关代码显示在列表 6中。
列表 6. 为一个称作 DerivedClass1 的类而产生的代码
#ifndef DERIVEDCLASS1_H
#define DERIVEDCLASS1_H
//Begin section for file DerivedClass1.h
//TODO: Add definitions that you want preserved
//End section for file DerivedClass1.h
#include "BaseClass.h"
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
class DerivedClass1 : BaseClass
{
};
#endif
|
C++ 转换还提供了一个构架,它可以运用在一般称作cpp_generalization的情况下。这个建模下有它自己的属性,它们可以使您为继承特性设置 access specifier,如图 6所示。
图 6. 应用这个 cpp_generalization 原型
产生的相关代码显示在列表 7中。
列表 7. 为带有 cpp_generalization 原型的 DerivedClass1 类产生的代码
#ifndef DERIVEDCLASS1_H
#define DERIVEDCLASS1_H
//Begin section for file DerivedClass1.h
//TODO: Add definitions that you want preserved
//End section for file DerivedClass1.h
#include "BaseClass.h"
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
class DerivedClass1 : public BaseClass
{
};
#endif
|
为 C++ 建模联合体
这部分帮助您理解如何利用 UML 来建模联合体。C++ 转换允许您通过提供一个cpp_union构件来建模,您必须首先对包含这个联合体的 UML 模型运用这个 CPP 转换文件。要建模这个联合体,可以添加一个 UML 类到这个模型,并添加这个 cpp_union 到它,如图 7所示。.
图 7. 为 C++ 建模联合体
这个构架包括一个叫作 isAnonymousUnion 的构架 (如图 7所示)。当您制定一个匿名的的联合体时,这个属性可以被设定为True。这个匿名联合体必须用元素嵌套,并且在这个模型的顶部并不存在。
产生的相关代码显示在列表 8中。
列表 8. 为联合体 Union1 产生的代码
#ifndef UNION1_H
#define UNION1_H
//Begin section for file Union1.h
//TODO: Add definitions that you want preserved
//End section for file Union1.h
//The top level union.
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
union Union1
{
//Begin section for Union1
//TODO: Add attributes that you want preserved
//End section for Union1
public:
//The anonymous union nested under Union1.
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
union
{
//Begin section for Union1::UnionNested
//TODO: Add attributes that you want preserved
//End section for Union1::UnionNested
}; //end union
private:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
int attribute1;
}; //end union Union1
#endif
|
利用 UML 建模的抽象类
抽象,正如您所知道的那样,是一个非常重要的 Object Oriented 概念,而且 Rational Software Architect 和 Rational System Developer 中的 C++ 转换允许您用这两种方法进行建模。第一种方法是利用 UML 模型元素, Interface。UML to C++ 转换的 UML 将它看作一个抽象类,并且产生反映相同特性的代码。例如,仔细考虑下面的模型:
- 创建一个拥有 Car and Trucke 类的 UML 模型。
- 这些类都是
工具 类型的例子。添加一个名为 Vehicle 的工具到这个 UML 模型中。
- 在这个建模面板中,选择 Interface Realization 并实现从类到接口的转变。
- 这个模型看起来应该如图 8所示。
图 8. 利用 C++ 建模接口
这个模型元素 Vehicle 的代码显示在列表 9中。尽管这些接口的定义与那些类定义十分相似,但是这些接口下面的操作通常是抽象的。您可以通过实现接口和类执行来执行这些抽象操作。在这些产生的代码中,这些类可以延伸这个接口所提供的操作。例如,在以上的模型中,这个 car 或者 truck 类可以重载 getNumberOfTyres() 和 getVehicleNumber() 操作的默认行为,从而为他们的例子定义具体的行为。
列表 9. 为接口 Vehicle 产生的代码
#ifndef VEHICLE_H
#define VEHICLE_H
//Begin section for file Vehicle.h
//TODO: Add definitions that you want preserved
//End section for file Vehicle.h
class Vehicle
{
//Begin section for Vehicle
//TODO: Add attributes that you want preserved
//End section for Vehicle
public:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
virtual int getNumberofTyres() = 0;
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
virtual int getVehicleNumber() = 0;
};
#endif
|
第二种建模抽象类模型的方法是拥有一个 UML 类(例如,Class1)。在这个类的 UML Properties 页签中,选择 Abstract 按钮从而制定这个抽象类概要,如图 9所示。
图 9. C++ 的抽象类实例
您应该在这些案例中使用抽象类,这些案例中只包含一定数量的需要在来自它的实例中被执行,然而您可以利用所有的方法都需要通过实例来实现的接口来完成,因此接口仅仅向世人表明这个对象的抽象看起来将是什么样子的。
利用 C++ 为属性建模默认值
当您在一个类中拥有一定的属性,您应该能够利用一些初始值来初始化这些属性。这不仅仅是一种您可以完成它的方法。您还可以根据后面例子的帮助来进一步理解它。首先,建模一个 拥有 Integer 类型数组属性的模型,它的维度是 [3][4]。这个属性的默认值在这个模型中已经设定,如图 10所示。
图 10. 利用 C++ 为属性创建默认值
要建模一个模型,可以按照以下这些步骤进行:
- 创建一个拥有 Class1 类的 UML 模型。
- 添加一个 Integer 类型的属性(attribute1)到这个类中。
- 在 Properties 页签中为这个属性设定默认值,如图 10所示。
- 在这个模型中转换配置就像一个源,可以激活 Properties 页签中的 Constructor 选项。
- 然后这个属性在构造函数中被初始化,如列表 10所示。
列表 10. 为初始化一个属性的默认值的构造函数而产生的代码
#include "Class1.h"
//Begin section for file Class1.cpp
//TODO: Add definitions that you want preserved
//End section for file Class1.cpp
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
Class1::Class1() :
attribute1(10) {
//TODO Auto-generated method stub
}
|
第二种创建模型的方法如下所示:
- 创建一个拥有 Class1 类的 UML 模型。
- 添加一个 Integer 类型的属性 (attribute1)到这个类,并为这个属性在Properties页签上设定它的默认值,如图 10所示。
- 在这个属性的 Properties 页签上,选择 Static 复选框,从而确保这个属性是静态的。
- 这些属性然后在主体文件中被初始化,并且静态属性也会被初始化。
列表 11. 为静态属性初始化一个属性的默认值而产生的代码
Source File:
#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
//@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
private:
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
static int attribute1[3][4];
}; //end class Class1
#endif
Body File:
#include "Class1.h"
//Begin section for file Class1.cpp
//TODO: Add definitions that you want preserved
//End section for file Class1.cpp
int Class1::attribute1[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
|
添加自定义的 ifndef 部分到 C++ 文件中
Rational Software Architect 为您提供灵活性从而可以添加更多的用户区域。例如,您可以为添加到 这个代码的数据段提供一个页签,从而以代码的形式添加更多的 ifndef 部分。您可以通过操作 Windows Preferences 页签来实现它,如图 11 所示。
图 11. 在 C++ 中自定义 ifndef 部分的例子
产生的相关代码显示在列表 12中。
列表 12. 为自定义 ifndef 部分生成的代码
//the customized ifndef section added
#ifndef OLD_CPP
using namespace KernelServices;
using namespace SystemServices;
#endif
#include "Class1.h"
//Begin section for file Class1.cpp
//TODO: Add definitions that you want preserved
//End section for file Class1.cpp
//@generated "UML to C++ (com.ibm.xtools.transform.uml2.cpp.CPPTransformation)"
bool Class1::Operation1() {
//TODO Auto-generated method stub
return 0;
}
|
您已经学到的内容
在这篇文章中,您已经学习了如何利用 Rational Software Architect 和 Rational Systems Developer 中的特性处理下面这些操作:
- 使用可变维度建模 C++ 中的数组
- 建模构造函数,析构函数,以及拷贝函数
- 建模赋值操作符
- 建模 getter 和 setter
- 建模 C++ 的继承
- 建模 C++ 的联合体
- 建模 UML 中的抽象类
- 建模 C++ 中属性的默认值
- 添加自定义的 ifndef 语句段到 C++ 文件中
参考资料 学习
获得产品和技术
讨论
作者简介  | |  | Vinod Varma 在过去的三年中一直从事于 IBM Rational 建模工具的开发工作。他担当过许多不同的建模工具的工作,如 Rational Rose、Rational Software Architect,以及 Rational System Developer。 |
 | |  | Pratima Gangalavoi 是工作在 Rational Software Architect 和 Rational Systems Developer 上的一名系统软件工程师,在 IBM Rational Software Bangalore 实验室工作。她主要工作于这些工具的 C++ 转换。 |
对本文的评价
|