继承 class 且成员包含其他继承 class 的成员?

Inherited class with member containing other inherited classes?

我正在尝试用 C++ 表示抽象语法树。 我有多个继承基础 class 'TreeNode' 的 classes。 其中一些包含指向其中的其他继承 class 的 TreeNode 的指针。 使用我试图用来让它工作的方法,我似乎无法访问子树节点中的成员。难道我做错了什么?有没有更好的方法来实现这个?

class TreeNode {};

class UnaryOperation : virtual public TreeNode {
public:
    TreeNodeType Type;
    UnaryOperationType Operation;
    TreeNode* Operand;
    UnaryOperation(UnaryOperationType operation, TreeNode* operand);
};

class BinaryOperation : virtual public TreeNode {
public:
    TreeNodeType Type;
    TreeNode* Left;
    BinaryOperationType Operation;
    TreeNode* Right;
    BinaryOperation(TreeNode* left, BinaryOperationType operation, TreeNode* right);
};

。 . .

TreeNode* unaryop_node = new UnaryOperation(op_type, operand_node);
return unaryop_node;

...

std::cout << (int)*unaryop->Type << std::endl;

class TreeNode 没有成员类型

作为一般说明,在 C++ 中,当您拥有指向某个类型的指针时,您只能访问该特定类型具有的 members/functions;您无法(直接)访问派生 class 中的任何 members/functions;这仅适用于例如通过转换或虚函数。

从您尝试通过 TreeNode 指针访问创建的 UnaryOperation 的方式来看,Type 似乎应该是基础 class TreeNode,类似于:

class TreeNode {
public:
    TreeNodeType Type;
};

class UnaryOperation : virtual public TreeNode {
public:
    UnaryOperationType Operation;
    TreeNode* Operand;
    UnaryOperation(UnaryOperationType operation, TreeNode* operand);
};

class BinaryOperation : virtual public TreeNode {
public:
    TreeNode* Left;
    BinaryOperationType Operation;
    TreeNode* Right;
    BinaryOperation(TreeNode* left, BinaryOperationType operation, TreeNode* right);
};

这假定 TreeNodeType 表示节点的类型,并且例如对于类型 UnaryOperation 的所有实例都是相同的;它可以被定义为

enum TreeNodeType { UnaryOp, BinaryOp };

请注意,在 C++ 的基础 class 中需要这样的“类型指示符”通常是一种 代码异味 ,表明您没有按照预期的方式进行继承在 C++ 中完成——通常您不需要区分 TreeNode 中包含的不同派生类型(因为您调用的虚函数会自动执行通用基指针中包含的特定子类型所需的操作),或者您应该有一个指向特定 class.

的指针

感谢您的所有回答。 事实证明我试图以错误的方式解决这个问题。我完全删除了 TreeNodeType 枚举,而是使用虚函数来遍历树。

class TreeNode {
public:
    TreeNode();
    virtual void print() = 0;
};

class UnaryOperation : public TreeNode {
public:
    UnaryOperationType Operation;
    TreeNode* Operand;
    UnaryOperation(UnaryOperationType operation, TreeNode* operand);
    void print() override {
        print_unaryop(Operation);
        Operand->print();
    }
};

class BinaryOperation : public TreeNode {
public:
    TreeNode* Left;
    BinaryOperationType Operation;
    TreeNode* Right;
    BinaryOperation(TreeNode* left, BinaryOperationType operation, TreeNode* right);
    void print() override {
        Left->print();
        print_binaryop(Operation);
        Right->print();
    }
};```

`unaryop_node->print();`