next up previous contents
Next: What belongs into the Up: Modularization, inheritance, templates, and Previous: Links, Simlinks, and Inheritance   Contents

Templates

Inheritance, without additional measures, does not work for graph reading and graph construction. It is not possible to do something like


{}
class Node ; // forward declaration
class Link {
    ...
    Node* toNode() { return toNode_ ; }
    ...
} ;
...
class SimLink : Link {
    ...
} ;
...
int main () {
    ...
    SimLink* aSimLink = new SimLink( ... ) ;
    ...
    SimNode* aSimNode = aSimLink->toNode() ;  // does not work
}
because toNode() is of type Node* instead of of type SimNode*.

For C programmers and many other people, it will be clear that it is possible to work around this problem: this is just about pointers, and it should be possible to cast pointers to whatever one wants. In general, it is however an advantage that C++ enforces consistency between pointer objects, and so one should not deliberately circumvent this type checking.

A possibility to work around this is the use of templates.


{}
template <class Node>   // <======
class Link {
    ...
    Node* toNode() { return toNode_ ; }
    ...
} ;
...
class SimNode ; // forward declaration
class SimLink : Link<SimNode> {  // <======
    ...
} ;
...
int main () {
    ...
    SimLink* aSimLink = new SimLink( ... ) ;
    ...
    SimNode* aSimNode = aSimLink->toNode() ;  // works
}

In fact, not much seems to have changed. What is the difference?

Template classes are often described as ``parameterized classes''. In fact, one could have written


{}
template <class XXnode>   // <======
class Link {
    ...
    XXNode* toNode() { return toNode_ ; }
    ...
} ;
where now the notation XXnode makes clear that the type of the node is left open.

Then, when later saying


{}
class SimNode ;
class SimLink : Link<SimNode> { 
    ...
} ;
then this means that SimLink inherits from Link while using SimNode everywhere where XXnode is in the definition. In consequence,


{}
aSimLink->toNode() ;
now returns a pointer to SimNode.

Thus, a method to translate everything we have done so far into a more general network construction is to write things like


{}
// --------------------------------------------
template <class Node>
class Link {
    ...
} ;
template <class Link>
class Node {
    ...
} ;
template <class Node,class Link>
class Net {
public:
    typedef map<Id,Node*> Nodes ;
    Nodes nodes ;
    ...    
    void readNodes() {...} ;
    ...
} ;
// --------------------------------------------
class SimNode ; // forward declaration
class SimLink : public Link<SimNode> {
    ...
} ;
class SimNode : public Node< SimLink> {
    ...
} ;
class SimWorld : public Net<SimNode,SimLink> {
    ...
} ;
// --------------------------------------------
int main () {
    ...
    SimWorld simWorld ;
    ...
    simWorld.readNodes() ;
    simWorld.readLinks() ;
    ...
}
// --------------------------------------------

In spite of the above explanation, for an inexperienced programmer the above is probably too much of a change to be done in one step and it will be necessary to achieve some familiarity with templates based on simpler programs before achieving this task. We hope that the above notes can guide the necessary reading and experimentation when templatization of the transportation simulation is the goal.


next up previous contents
Next: What belongs into the Up: Modularization, inheritance, templates, and Previous: Links, Simlinks, and Inheritance   Contents
2004-02-02