Home > Software engineering >  Passing a reference to an abstract class object
Passing a reference to an abstract class object

Time:11-17

I have an abstract syntax tree class which uses the visitor pattern. All constructors and the visit functions take in a reference to the abstract node 'ASTNode' or its derived classes.

class ASTNode {
public:
    virtual void accept(ASTVisitor& visitor) = 0;
};

class NameNode : public ASTNode {
public:
    NameNode(std::string name) : name(name) { }

    void accept(ASTVisitor& visitor) override;
    
    std::string name;
};

class ListNode : public ASTNode { 
public:
    ListNode(ElementSptr list) :  list(list) { }

    void accept(ASTVisitor& visitor) override;

    ElementSptr list;
};


class BinaryOperator : public ASTNode {
public:
    BinaryOperator(std::string kind, ASTNode& left, ASTNode& right)
    : kind(kind), left(left), right(right) { }

    void accept(ASTVisitor& visitor) override;

    std::string kind;
    ASTNode& left;
    ASTNode& right;
};

class ASTVisitor {
    public:
    virtual void visit(ASTNode& node) = 0;
    virtual void visit(NameNode& name) = 0;
    virtual void visit(ListNode& list) = 0;
    virtual void visit(BinaryOperator& bOp) = 0;
    virtual void visit(UnaryOperator& uOp) = 0;
};

I have a separate class that builds the actual tree and this is the function that does it. But the thing is, I can't create ASTNode root, left, right because it is abstract of course. When I add '&' to the definitions, it says that the variables 'root' requires initializer. I tried using pointers in this function to fix that and it did, however, if every child of the root is a pointer to an ASTNode, the existing tree will not work with it since it takes in references. So is there anyway to make this function work without pointers? :

The objective of this function is to return only the root node to the calling class and the calling class should then be able to do operations on its children:

ASTNode& TreeBuilder::buildTree(std::string expression){
    std::vector<std::string> tokens = split(expression);
    std::deque<ASTNode&> nodeStack;;
    std::deque<std::string> operatorStack;

    ASTNode root;
    ASTNode& left;
    ASTNode& right;

//generates tree from tokens 
 
return root;


}

CodePudding user response:

Since ASTNode is purely virtual you cannot construct an instance of it, moreover you should not use value semantics when dealing with polymorphic types, because of slicing.

Secondly in the example shown you return a reference to a local variable.

You should either use pointers (as you mentioned) and construct the tree on the heap. Or you pass a root node to the function by reference:

void TreeBuilder::buildTree(ASTNode& root, std::string expression){
    //generates tree from tokens 
}
  • Related