Working with typedefs
In C++, typedefs are intensively used to introduce compiler-controlled simple types used as short names for complex types. Objecteering C++ Developer lets you easily create typedefs of arbitrary complex types.
To create a C++ typedef, you simply create a UML datatype with the intended typedef name in the model. To specify the represented C++ type, the datatype is decorated by the "Cxx.TypeExpr" tagged value, and the C++ type expression is provided in the in the first tagged value parameter.
Because C++ permits very complex recursive type definitions, you can put the "$name" ACT macro in the type expression to specify exactly where the typedef name should be injected. If the "$name" macro is not specified, it is automatically added at the end of the type expression.
Objecteering C++ Developer translates the UML datatype into the C++ typedef declaration by adding the "typedef" keyword and substituting the "$name" macro by the typedef name. The datatypes defined in a class are generated in the class definition, while the datatypes defined in a package are generated in the package namespace in the package header file.
For example, we want to define the task handlers in the "Task" class. Task handlers are specific functions that run when certain conditions in the task are satisfied, for example, when the task is completed or delayed. A task handler is represented by the pointer to a function, which takes the "Task" instance as a parameter and returns a Boolean status.
To represent the task handlers, we introduce the "TaskHandler" typedef in the "Task" class, which expresses this pointer to a handler function. We then create the "TaskHandler" datatype in the "Task" class and decorate this datatype by the "Cxx.TypeExpr" tagged value with the following expression:
bool (*$name)(Task* theTask)
Figure 57 illustrates these operations.

Figure 57. The result of the operations you have just carried out
We now continue by defining the newly-created datatype as having public visibility. Objecteering C++ Developer produces the following code for the "Task" class.
//includes for used library types
#include <string>
#include <set>
#include <list>
//automatic includes (friends,
associated classes, etc)
#include "MyPlanner/TaskManagement/SimpleProject.h"
#include "MyPlanner/TaskManagement/HumanResource.h"
namespace MyPlanner
{
namespace TaskManagement
{
class Task
{
//typedefs
public:
typedef
bool (*TaskHandler)(Task* theTask);
//attributes
public:
std::string
name;
std::string
wbsCode;
//associations
protected:
SimpleProject*
project;
std::set<Task>
subTasks;
Task*
owner;
std::list<HumanResource>
resource;
//operations
public:
Task();
Task(const Task& value);
Task&
operator =(const
Task& value);
~Task();
bool addSubTask(int
wbsNum, Task& SubTask);
std::string
getName();
void setName(std::string value);
std::string
getWbsCode();
SimpleProject*
getProject();
std::list<HumanResource>&
getResource();
std::set<Task>&
getSubTasks();
Task*
getOwner();
void setOwner(Task* value);
//non-modeled members
};
}
}
After this, we can easily create attributes of "TaskHandler" type. For example, let's create the "handlers" attribute that models the mapping of handlers assigned to the given events for the task, and then create its model-level accessor. With the help of the accessor, we can assign our handlers to given events for a given task, and our code is concise due to the use of typedef (Figure 58).

Figure 58. The "handlers" attribute and the ""getHandlers" accessor
Objecteering C++ Developer produces the following code for the "getHandlers" accessor definition, where the typedef defined in the "Task" class is correctly referred to.
//class header file
#include "MyPlanner/TaskManagement/Task.h"
namespace MyPlanner
{
namespace
TaskManagement
{
//...
std::hash_map<std::string,Task::TaskHandler>&
Task::getHandlers()
{
//modifiable
zone @16423@30671900:2486@T
return handlers;
//modifiable
zone @16423@30671900:2486@E
}
}
}