我有两个用于string和int的包装器类,一个用于表示二进制操作和重载运算符 << 以字符串格式写入它们。不幸的是,我不能超载 << 没有 friend virtual 不能使用 具有 事实上的 !!
<<
friend
virtual
事实上的
#include <iostream> #include <string> class AST {}; class expr: public AST {}; class operator_: public AST {}; class BinOp: public expr { private: expr *_left; expr *_right; operator_ *_op; public: BinOp(expr *p_left, expr *p_right, operator_ *p_op):_left(p_left),_right(p_right),_op(p_op) {} friend std::ostream &operator<< (std::ostream &out, const BinOp &binop) { out << (binop._left) << " " << (binop._op) << " " << (binop._right); } }; class LShift: public operator_ { public: LShift() {} friend std::ostream &operator<< (std::ostream &out, const LShift &lshift) { out << "<<"; } }; class Name: public expr { private: std::string _id; public: Name(std::string p_id) { _id = p_id; } friend std::ostream &operator<< (std::ostream &out, const Name &name) { out << name._id; } }; class Num: public expr { private: int n; public: Num(int p_n) { n = p_n; } friend std::ostream &operator<< (std::ostream &out, const Num &num) { out << num.n; } }; int main() { auto name = Name("x"); auto num = Num(5); auto lshift = LShift(); auto binop = BinOp(&name, &num, &lshift); std::cout << binop << '\n'; return 0; }
所以上面提到的程序输出指针,
0x7ffd05935db0 0x7ffd05935d8b 0x7ffd05935d8c
x << 5
但我要说的是,流插入操作符是一个例外。
解决方案是重载操作符一次,并将其转发到更易于重写的函数。
class AST { public: virtual void print(std::ostream& s) const = 0; virtual ~AST() {} // you probably want this one too }; // no need for friendliness std::ostream& operator <<(std::ostream& s, const AST& node) { node.print(s); return s; }
print 每个类的重写。
print
但我也觉得有必要指出 AST 在AST中,树中的单个节点。运算符是表达式的一部分。整棵树都不一样。
AST
您应该有单独的层次结构根 operator_ 和 expr
operator_
expr