【问题标题】:How to call a virtual function from a pointer to a parent class如何从指向父类的指针调用虚函数
【发布时间】: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的代码在哪里?
  • Code does not compile,请修复。
  • 很抱歉,不小心粘贴了错误类型的表达式的代码。还在顶部添加了基础访问者类。
  • 您提供的信息不完整(例如对未定义类型的引用)。但是你可以让编译器给出诊断,帮助你找到你的问题(在你的实际代码上),方法是(1)在基类中将函数指定为纯虚函数(没有什么能阻止你定义纯虚函数)和( 2) 覆盖它时,使用override 标识符。假设您的问题不是悬空指针,我怀疑您通过 VALUE 作为基础传递派生类的对象,因此获取对象切片(我的建议将触发对后者的诊断)

标签: c++ pointers inheritance polymorphism virtual-functions


【解决方案1】:
Unary(Token oper, Expr<T> right) : oper(oper), right(&right) { }

这会将字段right 初始化为指向构造函数参数right。当构造函数退出时,参数被销毁,字段right变成一个悬空指针。

参数的类型应该是Expr&lt;T&gt;&amp;Expr&lt;T&gt;*

【讨论】:

  • 工作就像一个魅力!非常感谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
  • 2011-03-04
  • 2011-10-08
  • 2020-11-10
  • 2021-07-07
相关资源
最近更新 更多