В общем, наличие перегрузки операторов полиморфизмом в одном и том же классе является признаком того, что вы смешиваете классы стиля значений и классы стиля идентичности и, следовательно, специфический для C ++ запах кода.
Но ясказал бы, что оператор вставки потока является исключением.
Решение состоит в том, чтобы перегрузить оператор один раз и перейти к функции, более поддающейся переопределению.
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
каждого класса.
Но я также чувствую необходимость заметить, что ваш класс AST
не кажется полезным.На самом деле нет ничего общего между оператором и двоичным выражением.Также концептуально неправильно говорить, что оператор или выражение - это абстрактное синтаксическое дерево.Выражение - это часть AST, единственного узла в дереве.Оператор является частью выражения.Все дерево - это нечто иное.
У вас должны быть отдельные корни иерархии для operator_
и expr
.И да, это, вероятно, означает, что вам придется печатать дважды.Оно того стоит.