我正在使用C ++虚拟功能。我有一个基类treeNode和两个派生类的splitNode和leafNode。 splitNodes中的一些指针指向其他节点,可以是splitNode或leafNode。在运行时,如何检查指针是指向叶子还是拆分节点,而不改变节点的结构(即,我不想向它们添加任何新函数)。
此致
答案 0 :(得分:3)
目前尚不清楚为什么要这样做,但您可以使用dynamic_cast
:
treeNode* theNode = ....;
splitNode sNode* = dynamic_cast<splitNode*>(theNode);
bool isSplitNode = sNode != nullptr;
或只是
bool isSplitNode = dynamic_cast<splitNode*>(theNode);
如果正确使用多态,则不必执行此操作。
答案 1 :(得分:2)
在基类中实现虚拟GetType方法,并在子类中覆盖它。 这是最有效的方式。
记住Open closed principle。你应该利用多态性。
答案 2 :(得分:1)
您可以使用dynamic_cast
或typeid运算符执行此操作。但是,通常这是一个非常糟糕的主意。如果您的虚函数需要知道对象的确切类型,那么您的设计就会出现问题。
如果您遇到这种情况:
class treeNode
{
virtual int foo()
{
// do some default thing, maybe nothing
}
};
class splitNode : public treeNode
{
virtual int foo()
{
// do whatever splitNode wants to do
}
};
class leafNode : public treeNode
{
virtual int foo()
{
// do whatever leafNode wants to do
}
};
你有一个指向treeNode *p;
或splitNode
对象的指针leafNode
,你调用p->foo()
,然后调用适当版本的foo()
将被调用。这就是虚函数的重点。
另请参阅this question。
答案 3 :(得分:0)
拥有枚举成员的类型,或者返回子节点数的虚函数。就个人而言,我只会有一个带有枚举的节点类(或叶子的空子指针)。
答案 4 :(得分:0)
您可以使用typeid
运算符获取指向runtime-polymorphic对象的指针的基础类型。这是一个适合您描述的设计的示例:
struct treeNode
{
};
struct splitNode : treeNode
{
treeNode* left;
treeNode* right;
};
struct leafNode : treeNode
{
bool disabled;
};
void traverse(splitNode* node);
void traverse(leafNode* node);
void traverse(treeNode* node)
{
if(typeid(*node) == typeid(leafNode))
{
return traverse(static_cast<leafNode*>(node));
}
return traverse(static_cast<splitNode*>(node));
}
请注意dynamic_cast
几乎完全相同。
与在基类中存储某种形式的type-id并使用typeid
相比,static_cast
的性能可能较差。尽管有这些警告,但它对于非性能关键的代码(例如大多数代码)非常有用。