У меня есть этот базовый класс
struct Expr
{
virtual void accept(std::shared_ptr<const Expr> &expr, ExprVisitor &visitor) = 0;
explicit Expr() = default;
virtual ~Expr() = default;
};
И некоторые подклассы, например:
struct Binary : Expr
{
explicit Binary(Expr &left, Token &_operator, Expr &right);
Expr left;
Token _operator;
Expr right;
void accept(Expr &expr, ExprVisitor &visitor) override;
};
struct Grouping : Expr
{
explicit Grouping(Expr &expression);
Expr expression;
void accept(Expr &expr, ExprVisitor &visitor) override;
};
Теперь, поскольку Expr имеет чисто виртуальную функцию, невозможно иметь объект Expr, но я хочу , в качестве аргументов для двоичных и группирующих конструкторов, для них нужно взять другие двоичные выражения / выражения группировки / подкласса. Как мне это сделать?
Есть ли способ передать в качестве аргумента "любой подкласс X", я никогда не хочу, чтобы X был допустимым аргументом (на самом деле это невозможно сделать, поскольку это абстрактный класс )
Я думал об использовании умных указателей, кто-нибудь может привести пример?
РЕДАКТИРОВАТЬ
Итак, я попробовал реализации интеллектуальных указателей, но у меня возникают проблемы с взаимодействием других классов с интеллектуальными указателями:
// expr_impl.hpp
struct Binary : Expr
{
explicit Binary(std::shared_ptr<const Expr> &left, Token &_operator, std::shared_ptr<const Expr> &right);
std::shared_ptr<const Expr> left;
Token _operator;
std::shared_ptr<const Expr> right;
void accept(std::shared_ptr<const Expr> &expr, ExprVisitor &visitor) override;
};
struct Grouping : Expr
{
explicit Grouping(std::shared_ptr<const Expr> &expression);
std::shared_ptr<const Expr> expression;
void accept(std::shared_ptr<const Expr> &expr, ExprVisitor &visitor) override;
};
struct LiteralExpr : Expr
{
explicit LiteralExpr(Literal &literal);
const Literal literal;
void accept(std::shared_ptr<const Expr> &expr, ExprVisitor &visitor);
};
// expr_impl.cpp
Binary::Binary(std::shared_ptr<const Expr> &left, Token &_operator, std::shared_ptr<const Expr> &right) : left(left), _operator(_operator), right(right) {}
void Binary::accept(std::shared_ptr<const Expr> &expr, ExprVisitor &visitor)
{
visitor.visit(*this);
}
Grouping::Grouping(std::shared_ptr<const Expr> &expression) : expression(expression) {}
void Grouping::accept(std::shared_ptr<const Expr> &expr, ExprVisitor &visitor)
{
visitor.visit(*this);
}
LiteralExpr::LiteralExpr(Literal &literal) : literal(literal) {}
void LiteralExpr::accept(std::shared_ptr<const Expr> &expr, ExprVisitor &visitor)
{
visitor.visit(*this);
}
// exprvisitor.hpp
struct ExprVisitor
{
virtual void visit(Binary &expr) = 0;
virtual void visit(Grouping &expr) = 0;
virtual void visit(LiteralExpr &expr) = 0;
virtual void visit(Unary &expr) = 0;
explicit ExprVisitor() = default;
virtual ~ExprVisitor() = default;
};
// astprinter.hpp
struct AstPrinter : ExprVisitor
{
void visit(Binary &expr) override;
void visit(Grouping &expr) override;
void visit(LiteralExpr &expr) override;
void visit(Unary &expr) override;
std::string result;
std::string getResult();
};
// astprinter.cpp
void AstPrinter::visit(Binary &expr)
{
result += "(";
result += expr._operator.lexeme;
expr.accept(expr.left, *this);
// expr.accept(expr.right, *this);
result += ")";
}
void AstPrinter::visit(Grouping &expr)
{
}
void AstPrinter::visit(LiteralExpr &expr)
{
}