我目前正在将一些代码从 ANTLR4 的 C# 版本移植到 C++ 目标,并且我目前遇到了一些问题。我在 C# 中构建我的 AST 的方法是创建一个基类(我们称之为 Base)和派生类(我们称之为派生),其中包含我可以用来实现所述类的虚函数。
但是,尝试将此代码转换为 C++ 时,我不断收到 bad_cast 异常,我已将其范围缩小到 antlrcpp::Any 未正确将派生类转换为其基类。例如:
class Base {
public:
virtual std::string ToString() const { return "Base\n"; }
};
class Derived : public Base {
public:
std::string ToString() const override { return "Derived\n"; }
};
int main() {
Derived value;
std::cout << value.ToString(); //Obviously prints out Derived
Base& base_value = value;
std::cout << base_value.ToString(); //Still works exactly as expected and prints Derived
auto any = antlrcpp::Any(value);
auto derived = any.as<Base>(); //internally uses a dynamic_cast and throws a bad_cast
std::cout << derived.ToString(); //never gets to here
}
Run Code Online (Sandbox Code Playgroud)
我最初认为这可能是因为它只适用于指针,但是
auto any = antlrcpp::Any(new Derived());
std::cout << any.as<Base*>()->ToString(); //throws bad_cast
Run Code Online (Sandbox Code Playgroud)
我将其更改dynamic_cast为static_cast标题内部的a并且它会投射,但是它会打印出“Base”。当任何数据成员被访问时,C 风格的强制转换会导致崩溃。
我究竟如何使用antlrcpp::Any来获取基类?有什么明显的我遗漏了吗?
如果这是不可能的,我该如何解决这个问题?有 .is() 方法,但是在很多情况下,检查访问者的返回值是否属于某种类型是不可行的(例如对于表达式,可以有 30-40 个运算符)。
该antlrcpp::any课程不是为这种情况而设计的。这不是通用的变体实现。
如果您需要,您应该考虑使用各种类型的联合等的自己的变体实现,这不适用于类型擦除。
一般来说,在这种情况下,唯一指针可能不是一个好主意,因为它们不支持复制语义(并且您在这里需要它)。为了与访客进行评估,最好选择 a shared_ptr。