我有一个看起来像这样的令牌类:
class Token
{
public:
typedef enum { STRTOK, INTTOK } Type;
virtual bool IsA(Type) = 0;
}
class IntTok : public Token
{
int data;
public:
bool IsA(Type t) { return (t == INTTOK); }
int GetData() { return data; }
}
IntTok newToken;
if ( newToken.IsA(Token::INTTOK )
{
//blah blah
}
所以基本上我必须在Token类中定义每个子类;这并不是很糟糕,因为子类很少,我无法想象它们会发生变化。但是,它仍然比使用动态强制转换识别子类更丑陋,更糟糕且更不“正确”。但是:
IntTok newToken;
IntTok* tmpTokenTest = dynamic_cast<IntTok*>(&newToken);
if ( tmpTokenTest != NULL )
{
//blah blah
}
也非常笨拙。特别是当我必须在一个大的嵌套if中将它们串在一起时。
那你会用哪个?还有另一个解决这个问题的方法吗?
注意:我知道无论如何我都要投他们来获取他们各自的数据,但是
注意2:上面的代码中没有指出这些令牌也是一个链表。这会使模板变得困难(Token<int>
可能指向Token<string>
等。这就是为什么我需要一个Token类作为父类开始。
答案 0 :(得分:3)
只需使用虚拟功能来做你想做的事。而不是:
if(newToken.IsA(Token::INTTOK))
{
// do stuff with ((IntTok*)&newToken)->GetData()
}
这样做:
class Token
{
public:
...
virtual void doTypeDependentStuff() {} // empty default implementation
}
class IntTok : public Token
{
public:
...
void doTypeDependent()
{
// do stuff with data
}
}
答案 1 :(得分:3)
class TokenVisitor {
public:
virtual ~TokenVisitor() { }
virtual void visit(IntTok&) = 0;
virtual void visit(StrTok&) = 0;
};
class Token {
public:
virtual void accept(TokenVisitor &v) = 0;
};
class IntTok : public Token {
int data;
public:
virtual void accept(TokenVisitor &v) {
v.visit(*this);
}
int GetData() { return data; }
};
然后只需实现访问者界面并调用
token->accept(myVisitor);
将向访问者提供控制权,然后访问者可以采取适当的措施。如果你需要在本地和正确的类型中使用变量 - 那么你将难以绕过它。但我认为使用虚函数驱动控制到特定实现通常是解决它的好方法。
答案 2 :(得分:2)
我建议使用Boost :: Variant,它基本上是多种类型的联合(类型变量的对象可以容纳Ti类型的任何对象(1&lt; = i&lt; = n))。
使用它,您不必使用继承。
有关详细信息,请参阅there。
答案 3 :(得分:0)
所以基本上我必须在Token类中定义每个子类
你能解释一下原因吗?
真的有必要施放吗?可以使用多态函数。
或者,也许你可以有一个模板化的Token类(对某些人有默认行为)并且专门用于剩下的。
答案 4 :(得分:0)
这是一个令人讨厌的问题,但我更倾向于选择使用RTTI的版本。
不是新的C ++编译器(我最后在VC 6.0中尝试过,当它不受支持时)假设是typeid运算符,所以你不需要一个完整的动态转换?