C++通过父类Expr指针调用虚accept函数仅触发基类实现,如何解决?
问题原因
问题出在Unary类的构造函数参数设计上,你触发了对象切片问题:
Unary构造函数的第二个参数是Expr<T> right,属于值传递。当你传入派生类LiteralExpression对象lit时,会先调用基类Expr的拷贝构造函数,把派生类的独有内容全部切掉,生成一个临时的基类Expr对象作为形参right。- 你后续取
&right赋值给成员指针right,这个指针指向的本身就是一个基类对象,自然调用的是基类的accept方法,而且更严重的是这个临时对象在构造函数执行完就会被销毁,你存的指针是野指针,后续访问会触发未定义行为。
修复方案
把Unary构造函数的参数改成指针或者左值引用,避免值传递触发的对象切片即可:
// 改法1:用指针传递,修改构造函数定义 Unary(Token oper, Expr<T>* right) : oper(oper), right(right) { } // 对应构造调用时传地址 Unary<std::string> unary(Token(MINUS, "-", Literal(true), 1), &lit); // 改法2:用左值引用传递,修改构造函数定义 Unary(Token oper, Expr<T>& right) : oper(oper), right(&right) { } // 构造调用可以和你原来的写法完全兼容,直接传lit即可
修改后再调用unary.right->accept(this)就会正确调用到LiteralExpression的accept方法。
内容的提问来源于stack exchange,提问作者diego_rod
相关产品推荐
相关产品推荐

