 | Level: Intermediate Vinod V. Uddaraju (vinod.varma@in.ibm.com), Staff Software Engineer,
IBM
Pratima Gangalavoi (pratima.g@in.ibm.com), Systems Software Engineer,
IBM
12 Feb 2008 This article (Part 3 of a series) provides you with tips to better understand how to construct C++ specific models in UML to generate the code when you run the UML to C++ transformation in IBM® Rational® Software Architect or IBM® Rational® Systems Developer.
This article will show you how to model arrays, unions, abstract classes, default values for attributes, and so on. It also gives you some tips on how you can use Rational Software Architect features to further customize the code generated by the C++ transformation.
Modeling arrays in C++ with variable dimensions
This section discusses modeling arrays in C++ whose dimensions are specified as variables. To create a single dimensional array of the type a[m] (where m is an integer variable already defined and initialized), apply the cpp_type stereotype on the array variable a in the UML model. Next, set the array dimensions property of this stereotype to [m], as shown in Figure 1. To accomplish this, follow these steps:
-
Select the UML class attribute that has to be modeled as an array.
-
With the attribute still selected in the Project Explorer, switch to the Properties view, and then click the Stereotypes tab.
-
Click the Apply Stereotypes button and select the cpp_type stereotype.
-
Select the arrayDimensions property specified in the stereotype, and then specify the array dimensions, as shown in Figure1.
Figure 1. Specifying the dimensions for an array
The related generated code is shown in Listing 1.
Listing 1. Generated code for the array attribute in 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
|
Modeling constructor, destructor, and copy constructor
This section discusses modeling the constructor, destructor, and copy constructor for a C++ class. To generate these for a C++ class named Class1, follow these steps:
-
Create a UML class named Class1.
-
Go to the Properties tab of the UML to C++ Transformation configuration wizard and select the Constructor, Destructor, and Copy Constructor options, as shown in Figure 2.
Figure 2. Modeling constructors, destructors, and copy constructors
The related generated code is shown in Listing 2.
Listing 2. Code generated with constructors, destructors, and copy constructors
#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
|
Modeling the Assignment Operator
This section discusses modeling an assignment operator for a C++ class. To generate this assignment operator for a C++ class named Class1, perform these steps:
-
Create a UML class with name Class1
-
Go to the Properties tab of the Transformation Configuration wizard and select the Assignment option.
Figure 3. Modeling assignment operator for attributes
The related generated code is shown in Listing 3.
Listing 3. Code generated with assignment operator enabled
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
}
|
Modeling getters and setters
This section discusses modeling getters and setters for an attribute in a C++ class. To generate these for a C++ attribute in a C++ class with name Class1, follow these steps:
-
Create a UML class named Class1.
-
Add a UML attribute named attribute1 and set its type to Integer.
-
Then select the Getters and setters option in the Properties tab of the Transformation Configuration wizard.
-
The transformation configuration provides you with the further options to make these getters and setters Inline or By reference, by selecting these properties in the transformation configuration under Getters and setters, as shown in Figure 4.
Figure 4. Modeling getters and setters for attributes
The related generated code is shown in Listing 4 (Inline) and Listing 5 (By reference).
Listing 4. Code generated with the Getters and setters and Inline option
#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
|
Listing 5. Code generated with Getters and setters with the By reference option
#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
|
Modeling inheritance for C++
Inheritance is an important feature in Object Oriented Programming, and UML provides a way to model it. To model inheritance, use the generalization relationship provided by the UML modeling palette, which is drawn from the inherited class to the base class. For example, consider constructing a model that has multiple inheritances. In the model shown in Figure 5, the UML class DerivedClass1 derives from the common class called BaseClass.
Figure 5. Modeling inheritance for C++
The related generated code is shown in Listing 6.
Listing 6. Generated code for a class 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
|
The C++ transformation also provides a stereotype, which can be applied to the generalization called cpp_generalization. This stereotype has properties under it that enable you to set the access specifier for the inheritance drawn, as shown in Figure 6.
Figure 6. Applying the cpp_generalization stereotype
The related generated code is shown in Listing 7.
Listing 7. Generated code for a class with cpp_generalization stereotype for 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
|
Modeling unions for C++
This section helps you understand how to model unions using UML. The C++ transformation allows you to model this by providing a stereotype cpp_union. To create this, you must first apply the CPP transformation profile to the UML model that contains the union. To model a union, add a UML class to the model and add the cpp_union stereotype to it, as shown in Figure 7.
Figure 7. Modeling Unions for C++
This stereotype includes a property called isAnonymousUnion (as shown in Figure 7). This property can be set to True when you have to make a union anonymous. Anonymous unions have to be nested elements and cannot exist at the top level in a model.
The related generated code is shown in Listing 8.
Listing 8. Generated code for union 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
|
Modeling abstract classes in UML
Abstraction, as you know, is a very important Object Oriented concept, and the C++ transformation in Rational Software Architect and Rational System Developer allows you to model this in two ways. The first way to do this is to use the UML model element, Interface. The UML to C++ transformation treats this as an abstract class, and generates code to reflect the same. For example, consider the following model:
-
Create a UML model that has classes named Car and Truck.
-
These classes are instances of the
vehicle type. Add an interface named Vehicle to the UML model.
-
From the modeling palette, select the Interface Realization and draw these realizations from the classes to the interface.
-
The model should look like that shown in Figure 8.
Figure 8. Modeling interfaces in C++
The code for the model element Vehicle is shown in Listing 9. Although the definitions for these interfaces are similar to those of classes, the operations under these interfaces are always abstract. You can implement abstraction by having realizations between the interfaces and the class implementations. In the generated code, these classes can extend the operations given by the interface. For example, in the above model, the car or truck class can override the default behavior for the getNumberOfTyres() and getVehicleNumber() operations to define their behaviors specific to their instance.
Listing 9. Generated Code for an interfaceVehicle
#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
|
The second way of modeling abstract classes is to have a UML class (for example, Class1). In the UML Properties tab for this class, select the Abstract button to make the class abstract, as shown in Figure 9.
Figure 9. Example for abstract class for C++
You would use abstract classes in cases where only a certain number of methods contained in it need to be implemented in instances derived from it, whereas you can use interfaces where all the methods need to be implemented by the instances of it, and hence the interface only tells the world what the abstraction of the object would look like.
Modeling default values for attributes in C++
When you have attributes in a class, you need to be able to initialize these attributes with some initial values. There is more than one way in which you can accomplish this. You can understand this with the help of examples that follow. First, construct a model having an attribute which is of type Integer array, whose dimensions are [3][4]. The default value for this attribute is set in the model, as shown in Figure 10.
Figure 10. Modeling default values for attributes in C++
To construct a model, follow these steps:
-
Create a UML model having a class of Class1.
-
Add an attribute (attribute1) of type Integer to this class.
-
Set default value for this attribute in the Properties tab for this, as shown in Figure 10.
-
In the transformation configuration for this model as a source, enable the Constructor option in the Properties tab.
-
The attributes then gets initialized in the constructor, as shown in the Listing 10.
Listing 10. Generated code for the constructor initializing the default value for an attribute
#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
}
|
The second way to create this model is as follows:
-
Create a UML model having a class of Class1.
-
Add an attribute (attribute1) of type Integer array to this class, and set the default value for it in the Properties tab for the attribute as shown in Figure 10.
-
In the Properties tab for the attribute, select the Static check-box to make the attribute static.
-
The attributes then gets initialized in the body file where the static attributes get initialized.
Listing 11. Generated code for static attribute intializing the default value for an attribute
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}};
|
Adding customized ifndef sections to the C++ files
Rational Software Architect provides you with the flexibility to add more user regions. For example, you can add more #ifndef sections in the code by providing a tab for this to be added to the code. You can do this by going to the Windows Preferences tab, as shown in Figure 11.
Figure 11. Example for customizing ifndef sections in C++
The related generated code is shown in Listing 12.
Listing 12. Generated code for customizing an ifndef section
//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;
}
|
What you have learned
In this article, you have learned how to do the following using features in Rational Software Architect and Rational Systems Developer:
-
Model arrays in C++ with variable dimensions
-
Model constructor, destructor, and copy constructor
-
Model the assignment operator
-
Model getters and setters
-
Model inheritance for C++
-
Model unions for C++
-
Model abstract classes in UML
-
Model default values for attributes in C++
-
Add customized ifndef sections to the C++ files
Resources Learn
- Part 1 of this series,
"Tips and tricks for C++ transformations using Rational Systems Developer and Rational Software Architect" (developerWorks, Jun 2006) is a step-by-step guide to exposing C++ methods as services.
-
Part 2 of this series,
"Tips and tricks for C++ transformations using Rational Systems Developer and Rational Software Architect, Part 2" (developerWorks, Jan 2008) provides tips to help you achieve finer control of the C++ code generated when you run the UML to C++ transformation in IBM® Rational® Software Architect or IBM® Rational® Systems Developer.
-
For technical resources, visit the developerWorks Rational Systems Developer area. You'll find technical documentation, how-to articles, education, downloads, product information, and more.
-
Stay current with Technical events and Webcasts.
- Subscribe to the
developerWorks Rational zone newsletter.
Keep up with developerWorks Rational content. Every other week, you'll
receive updates on the latest technical resources and best practices for the
Rational Software Delivery Platform.
- Subscribe to the
Rational Edge newsletter
for articles on the concepts behind effective software development.
-
Browse the technology bookstore for books on these and other technical topics.
Get products and technologies
Discuss
About the authors  | |  | Vinod Varma has been a developer working on IBM Rational modeling tools for the past 3 years. He has worked on various modeling tools like Rational Rose, Rational Software Architect, and Rational System Developer. |
 | 
|  | Pratima Gangalavoi is a Systems Software Engineer working with Rational Software Architect and Rational Systems Developer at the IBM Rational Software Bangalore lab. She works on the C++ transform for those tools. |
Rate this page
|  |