【发布时间】:2021-12-04 13:49:24
【问题描述】:
我正在尝试从指向另一个类中的类的指针调用虚函数。无论我做什么,它都只是调用原始函数。我想我错过了一些简单的东西。这是重现问题的最小代码位。 Binary 和 LiteralExpression 继承自 Expr。他们每个人都实现了自己的接受方法。
template <typename T>
class LiteralExpression;
template <typename T>
class Unary;
template<typename T>
class Visitor {
public:
virtual T visitLiteralExpressionExpr(LiteralExpression<T> expr) { T temp; return temp; };
virtual T visitUnaryExpr(Unary<T> expr) { T temp; return temp; };
};
template<typename T>
class Expr {
public:
virtual T accept(Visitor<T>* visitor) { std::cout << "base accept" << std::endl; T temp; return temp; };
};
template<typename T>
class Unary : public Expr<T> {
public:
Unary(Token oper, Expr<T> right) : oper(oper), right(&right) { }
T accept(Visitor<T>* visitor) {
std::cout << "unary accept" << std::endl;
return visitor->visitUnaryExpr(*this);
}
Token oper;
Expr<T> *right;
};
template<typename T>
class LiteralExpression : public Expr<T> {
public:
LiteralExpression(Literal lit, TokenType type) : lit(lit), type(type) { }
T accept(Visitor<T>* visitor) {
std::cout << "literal accept" << std::endl;
return visitor->visitLiteralExpressionExpr(*this);
}
Literal lit;
TokenType type;
};
在这里我测试是否调用了正确的接受方法。我构建了一个带有负号的一元表达式对象和一个 LiteralExpression 对象,因为它是正确的“叶子”。如果我调用一元表达式的 accept 一切正常,如果我直接调用 LiteralExpression 的 accept 方法,它也可以正常工作。但是,如果我尝试通过指向它的指针作为 Expr 对象调用 LiteralExpression 的接受方法,它会改为调用基本接受方法。
void AstPrinter::test()
{
LiteralExpression<std::string> lit(Literal(123), INTEGER);
Unary<std::string> unary(Token(MINUS, "-", Literal(true), 1), lit); // -123
lit.accept(this); // prints "literal accept"
unary.accept(this); // prints "unary accept"
unary.right->accept(this); // prints "base accept"
}
任何帮助将不胜感激! (忽略未封装/非 const 实例数据,仅用于调试)
【问题讨论】:
-
Unary的代码在哪里? -
很抱歉,不小心粘贴了错误类型的表达式的代码。还在顶部添加了基础访问者类。
-
您提供的信息不完整(例如对未定义类型的引用)。但是你可以让编译器给出诊断,帮助你找到你的问题(在你的实际代码上),方法是(1)在基类中将函数指定为纯虚函数(没有什么能阻止你定义纯虚函数)和( 2) 覆盖它时,使用
override标识符。假设您的问题不是悬空指针,我怀疑您通过 VALUE 作为基础传递派生类的对象,因此获取对象切片(我的建议将触发对后者的诊断)
标签: c++ pointers inheritance polymorphism virtual-functions