1

There exists an interface

#pragma once
#include <string>
#include <vector>

enum type_node {
   NONTERMINAL;
   TERMINAL;
}

class Node {
public:
    Node(type_node);

    virtual ~Node();

    type_node node_type;
}
Node::Node(type_node TYPE) {
    node_type = TYPE;
}

And two child classes

#pragma once
#include <Node.h>

class Nonterminal: public Node{
public:
    Nonterminal();
    ~Nonterminal();

    std::vector<Node *> children;
    void attach(std::vector<Node *>);
}
#pragma once
#include "Node.h"

class Terminal: public Node{
public:
    Terminal();
    ~Terminal();
}

Nonterminal is implemented as follows omitting the empty destructor.

NonterminalNode::NonterminalNode() : Node(NONTERMINAL) {
}

void NonterminalNode::attach(std::vector<Node *> CHILDREN) {
    children = CHILDREN;
}

One would like to be able to populate a tree like structure

NonterminalNode * node_1 = new NonterminalNode;
NonterminalNode * node_2 = new NonterminalNode;
TerminalNode * node_3 = new TerminalNode;

node_1->attach({ node_2, node_3 });

Now a new sub-tree would like to be added to node_2 but accessed through node_1

NonterminalNode * node_1 = new NonterminalNode;
NonterminalNode * node_2 = new NonterminalNode;
TerminalNode * node_3 = new TerminalNode;
TerminalNode * node_4 = new TerminalNode;
TerminalNode * node_5 = new TerminalNode;

node_1->attach({ node_2, node_3 });

node_1->children[0]->attach({ node_4, node_5 }); // Error attach is not a virtual method

You could make attach a virtual method and implement it in both classes but this violates good OOP practices as TerminalNode has no need for an attach method.

The interface-segregation principle (ISP) states that no client should be forced to depend on methods it does not use.

You could also use dynamic_cast but this function could become expensive should you wish to add many sub-trees as the pointer conversion is nontrivial.

How can the desired behaviour be achieved without violating these two constraints?

Ivor Denham-Dyson
  • 655
  • 1
  • 5
  • 24
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/204342/discussion-on-question-by-jake-denham-dyson-avoiding-reinterpret-cast-in-difficu). – Samuel Liew Dec 16 '19 at 11:54
  • If you need to store objects of a fixed set of types in the same container, and those types do not have a common interface, `std::variant` is a great fit. See [this answer](https://stackoverflow.com/a/59319720/1863938) for details. – parktomatomi Dec 16 '19 at 19:34

0 Answers0