3
\$\begingroup\$

I want to establish a hierarchy, where at each level of the hierarchy, each type can contain a list<its own type>. So Node (root of object class hierarchy) contains a list<Node*>, SpecialNode : Node contains a list of SpecialNode. SpecialNode should not "accidentally" put new SpecialNode children into the list<Node*> in the base class, so the list<> are private.

I personally hate the concept of namehiding, because it is extremely prone to mistakes, uninitialized values, etc. So here I have made it impossible (via private) for SpecialNode to "accidentally" insert into the list<Node*> instead of its own list<SpecialNode*>.

struct Node
{
private:
  list<Node*> children ;

protected:
  int v ;

public:
  Node( int iv ) : v(iv) { }

  virtual void print( const char* msg )
  {
    printf( "REGULAR CHILD %d in %s\n", v, msg ) ;
    for( Node *sn : Node::children )
      sn->print( "regular" ) ;

  }
} ;

struct SpecialNode : public Node
{
private:
  list<SpecialNode*> children ;

public:
  SpecialNode( int iv ) : Node(iv) { }
  void add( SpecialNode* child ) {
    children.push_back( child ) ;
  }

  void print( const char* msg )
  {
    printf( "SPECIAL CHILD %d in %s\n", v, msg ) ;
    for( SpecialNode *sn : children )
      sn->print( "special" ) ;

    //for( Node *sn : Node::children )
    //  sn->print( "regular" ) ;
  }

} ;

int main(int argc, const char * argv[])
{
  SpecialNode *sn = new SpecialNode( 1 ) ;

  // SpecialNodes must contain SpecialNode children.
  sn->add( new SpecialNode( 2 ) ) ;
  //sn->children.push_back( new Node( 3 ) ) ; // fails b/c Node is too basic to fit in SpecialNode container.

  sn->print( "root" ) ;

}

Is this a good way to do this, or is there a better way?

\$\endgroup\$
  • \$\begingroup\$ What are you trying to achieve with this? From your code it looks like you're only inheriting from Node so that you can have a 'level' to each node, is there a specific need to have a child with a parent each with a list of references to its own type (keep in mind that std::list<SpecialNode> will contain a std::list<Node> as well adding numerous levels of complexity)? \$\endgroup\$ – txtechhelp Dec 18 '13 at 19:48
  • \$\begingroup\$ I'm trying to 1) Concrete each class' list<self> as its own type. 2) Avoid name hiding errors and mistakes \$\endgroup\$ – bobobobo Dec 18 '13 at 20:29
  • \$\begingroup\$ That's the mechanism you're trying to find, but why do you need it? Since a SpecialNode* can be stored in any Node*, such as the private list<Node*> if Node had an add(), but then unlike a Node it can't hold other Nodes, this sounds like a violation of LSP. \$\endgroup\$ – Michael Urman Dec 18 '13 at 21:32
  • \$\begingroup\$ your Node class has no add method in it at all, so you can never add any nodes to the base class. And you can only add SpecialNodes to the derived class. Perhaps what you would rather have are 2 separate classes with no relation or dependence on each other since you can't actually use these 2 together at all. \$\endgroup\$ – YoungJohn Dec 18 '13 at 23:17
1
\$\begingroup\$

You might prefer to not use polymorphism at all if you want to make sure that your types remain unique. Consider something more like:

class Node
{
private:
    list<Node*> children ;
    int v ;

public:
    Node( int iv ) : v(iv) { }

    void add( Node* child )
    {
        children.push_back( child );
    }

    void print( const char* msg )
    {
        printf( "REGULAR CHILD %d in %s\n", v, msg );
        for( Node *sn : Node::children )
        {
            sn->print( "regular" );
        }
    }
};

class SpecialNode // no inheritance
{
private:
    list<SpecialNode*> children;
    int v;

public:
    SpecialNode( int iv ) : v(iv) {}
    void add( SpecialNode* child )
    {
        children.push_back( child ) ;
    }

    void print( const char* msg )
    {
        printf( "SPECIAL CHILD %d in %s\n", v, msg ) ;
        for( SpecialNode *sn : children )
            sn->print( "special" ) ;
    }
};

class Composite // no inheritance
{
private:
    Node nodes;
    SpecialNode specialNodes;

public:
    Composite( int iv ) : nodes(iv), specialNodes(iv)
    void addSpecial( SpecialNode* child )
    {
        specialNodes.add( child ) ;
    }
    void add( Node * child)
    {
        nodes.add(child);
    }

    void print( const char* msg )
    {
        nodes.print(msg);
        specialNodes.print(msg);
    }
};
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.