处理C++结构中未知类型的最佳方法是什么?

kda*_*ani 4 c++ interpreter pointers void-pointers

我正在为一个简单的,类似Lisp的编程语言编写一个解释器.它将代码处理成节点,所有节点都有类型,其中一些可能具有索引顺序的子节点.由于信息性质的不同,我不能对所有节点值使用相同长度的类型.它们的类型名称是枚举类型,但我对值类型的唯一想法是void *.但是当我使用它时,我认为我必须非常小心.我的意思是,我不能使用任何默认的析构函数,我必须编写一个关心节点类型的析构函数.此外,我甚至需要使用大量的强制转换来访问值.

这就是我所说的:

enum NodeType {/* Some node types */}

class Node
{
public:
    Node(string input_code);
private:
    NodeType type; // Having this I can know the type of value
    void* value;
};
Run Code Online (Sandbox Code Playgroud)

有没有更安全的方法,制作更好的代码,但仍然像使用void指针一样高效?

Joh*_*ing 5

我能想到两种选择.一种是使用多态,其中有一个抽象基类,Node以及一些特定于类型的子类.也许是这样的:

class Node
{
public:
  virtual ~Node() = 0;
};

class String : public Node
{
public:
  ~String() {}
};

class Float : public Node
{
public:
  ~Float() {}
};
Run Code Online (Sandbox Code Playgroud)

存储这些节点时,您将存储Node*而不是存储void*.基类中存在(抽象)虚拟析构函数,可以通过基类指针正确地销毁具体对象,如下所示:

Node* obj = new String;
delete obj;
Run Code Online (Sandbox Code Playgroud)

您还可以调用在基类中声明的方法,并让它们在正确的派生类中执行代码,如果这些方法在基类中是虚拟的.这些通常也是纯虚拟的,例如:

class Node
{
public:
  std::string Speak() const = 0; // pure virt
};

class String : public Node
{
public:
  std::string Speak() const { return "Hello"; }
};
Run Code Online (Sandbox Code Playgroud)

另一种选择是使用某种变体类.C++本身没有内置于该语言的变体类,但是已经编写了一些库,例如Boost,它们提供了这样的类.