【发布时间】:2017-02-18 22:21:26
【问题描述】:
我正在用 C++11 实现我自己的编程语言。
我设计的数据类型之一是Token 类。它旨在存储从源文件读取的令牌,包括令牌的内容、类型以及遇到它的行。
标记可以是单字符符号、长字符串、数字或名称。所以它需要能够存储不同的数据类型,一个字符代表符号,一个双精度代表数字,一个 std::string 代表名称和字符串。
我实现这一点的方式是将该值存储在一个 void 指针中,并添加一个自定义枚举的属性,这有助于了解您应该将该 void 指针转换为什么类型。
当然,我可以为每个 Token 子类型创建一个类,但无论如何我都需要将它们全部存储为 Token*,这意味着我仍然需要一个对我有帮助的枚举知道我应该将 Token* 转换为什么类型。
这是它的实际代码:
enum token_type {
symbol,
number,
name,
string
};
struct Token {
void* value = nullptr;
token_type type;
unsigned int line;
Token(void* new_value, token_type new_type, unsigned int new_line):
value(new_value), type(new_type), line(new_line)
{}
~Token() {
switch (type) {
case symbol:
delete (char*) value;
break;
case number:
delete (double*) value;
break;
case name:
case string:
delete (std::string*) value;
}
}
};
有什么好的设计模式可以避免使用 void 指针和(可能)枚举?每个人都在告诉我这个设计是错误的,但是我没有关于如何真正改善这种情况的建议,所以我在这里问。
【问题讨论】:
-
你看过
boost::variant吗? -
嗯,大多数编译器都淹没在 void 指针中,所以我不会说使用它们一定是错误的,但是既然你知道你需要的数据类型,你可以考虑使用变体或类似的数据类型。
-
@Hayt 不确定我能否使用 boost。我正在使用 Linux 模拟器在 Android 上工作,但不存在 boost。也许我应该手动下载它。我仍然不确定它的便携性。
-
你可以试试。 Boost 有一个它可以构建的编译器的列表。如果你可以访问 C++17,那么你就有 std::variant 了。
-
@Hayt 刚刚尝试过。是的,我可以将 g++ 编译标志用于 c++17 (
-std=c++1z)。你能在此基础上给出答案吗?
标签: c++ c++11 void-pointers