【发布时间】:2015-04-10 21:42:05
【问题描述】:
我正在用 C++ 编写一个简单的解析器,旨在解析 s 表达式语言的子集。
我正在尝试以简洁的方式为标记器设计我的继承层次结构,但我遇到了对象切片问题,因为我一直在尝试避免动态分配。我想避免动态分配的原因是回避在我的标记器和解析器中引入内存泄漏的问题。
整体结构是:一个 Parser 有一个 Tokenizer 实例。解析器调用 Tokenizer::peek() 返回输入头部的标记。我希望 peek() 按值返回一个 Token 实例,而不是动态分配正确派生类的 Token 并返回指针。
更具体地说,假设有两种标记类型:Int 和 Float。这是一个有望澄清问题的示例:
class Token {
public:
virtual std::string str() { return "default"; }
};
template <typename T>
class BaseToken : public Token {
public:
T value;
BaseToken(const T &t) : value(t) {}
virtual std::string str() {
return to_str(value);
}
};
class TokenInt : public BaseToken<int> {
public:
TokenInt(int i) : BaseToken(i) {}
};
class TokenFloat : public BaseToken<float> {
TokenFloat(float f) : BaseToken(f) {}
};
Token peek() {
return TokenInt(10);
}
int main() {
Token t = peek();
std::cout << "Token is: " << t.str() << "\n";
return 0;
}
很明显,输出是“Token is: default”而不是“Token is: 10”,因为 TokenInt 被切分为 Token。
我的问题是:是否有适当的继承结构或设计模式可以在不使用动态分配的情况下完成这种类型的多态性?
【问题讨论】:
-
使用动态内存分配和智能指针。动态内存分配将解决对象切片问题。智能指针将处理内存管理问题。
标签: c++ parsing inheritance design-patterns