0

I am trying to write a toy language interpreter in C++. I am having trouble with the AST classes. The parent ASTNode class declares its left-branch and right-branch pointers as ASTNode*like this:

class ASTNode {

    public:
        ASTNode(NodeType newType, const ASTNode* left, const ASTNode* right);

        const ASTNode* getLeft() const;
        const ASTNode* getRight() const;

    protected:
        //node type omitted
        ASTNode* left;
        ASTNode* right;

}

The ASTNode class has a subclass called ValNode. It has a method that returns its value (stored in a member variable):

class ValNode : public ASTNode
{
    public:
        explicit ValNode(const Variant& newvalue);

        const Variant& getValue() const;

    private:
        Variant value;
}

When I execute the following code, the program crashes due to a failed dynamic_cast. What's wrong, and how can I fix it?

ASTNode* node = new ASTNode(NodeType::OP, new ValNode(1), new ValNode(2));
cout << dynamic_cast<const ValNode*>(node->getLeft())->getValue() << endl;
Techgineer
  • 153
  • 1
  • 10
  • Could you please post definition of the classes? – dividedbyzero Feb 13 '18 at 21:02
  • I assume left and right are not assigned in the ctor. Otherwise you would probably get a "assignment discards qualifiers" (const) error from the compiler. – cli_hlt Feb 13 '18 at 21:03
  • Don't use dynamic_cast. Do you think you need dynamic_cast? This means your design is broken at its core (or doesn't exist). I cannot fix your design but in general you should avoid data members in abstract classes, avoid deriving from concrete classes, and do all your polymorphic work in virtual functions. – n. m. could be an AI Feb 13 '18 at 21:05
  • @cli_hlt The constructor parameters are deep copied in the constructor. – Techgineer Feb 13 '18 at 21:05
  • @Techgineer I can't spot `Variant`? How does the `Variant` class/type comply with `ASTNode*`? Need to use a `dynamic_cast` is a serious _code/design smell_ BTW. –  Feb 13 '18 at 21:08
  • @TheDude Variant is a class that holds any primitive type and strings. It is unrelated to my problem. – Techgineer Feb 13 '18 at 21:10
  • @Techgineer _"It is unrelated to my problem. "_ Eeeer! The `dynamic_cast` fails on it but it's unrelated, sure. See my finger drawing down my lower lid. –  Feb 13 '18 at 21:12
  • @TheDude GDB clearly shows that the `dynamic_cast` fails and returns `nullptr`. I could have written `dynamic_cast(node->getLeft())->getLeft()` and had the same problem. – Techgineer Feb 13 '18 at 21:15
  • 1
    @Techgineer Well, we can't tell from your insufficient code example. How did you populate that tree for example? Post a [MCVE] please. –  Feb 13 '18 at 21:21
  • I once posted an AST as part of my answer to [SO: Parsing strings of user input using the cparse library from git](https://stackoverflow.com/a/46965151/7478597). – Scheff's Cat Feb 13 '18 at 21:21
  • @Techgineer *It is unrelated to my problem* -- Ok, so if that's the case, get [this to compile without error](http://coliru.stacked-crooked.com/a/ef4aaa23726f014d). – PaulMcKenzie Feb 13 '18 at 21:30
  • @PaulMckenzie Edited. Now it does – Techgineer Feb 13 '18 at 21:32
  • @Techgineer: "*The constructor parameters are **deep copied** in the constructor*" - that is a very suspicious statement. Please provide a [mcve] showing your actual `ASTNode` constructor implementation, not just its declaration. – Remy Lebeau Feb 13 '18 at 21:45

1 Answers1

0

There is no need to do a dynamic cast here. You can use:

static_cast<const ValNode*>(node->getLeft())->getValue()
20knots
  • 527
  • 1
  • 6
  • 16