我正在使用 C++ 虚函数。我有一个基类treeNode 和两个派生类splitNode 和leafNode。splitNodes 中的一些指针指向可能是 splitNode 或 LeafNode 的其他节点。在运行时,如何在不更改节点结构的情况下检查指针是否指向叶节点或拆分节点(即,我不想向它们添加任何新函数)。
问候
我正在使用 C++ 虚函数。我有一个基类treeNode 和两个派生类splitNode 和leafNode。splitNodes 中的一些指针指向可能是 splitNode 或 LeafNode 的其他节点。在运行时,如何在不更改节点结构的情况下检查指针是否指向叶节点或拆分节点(即,我不想向它们添加任何新函数)。
问候
目前尚不清楚您为什么要这样做,但您可以使用dynamic_cast
:
treeNode* theNode = ....;
splitNode sNode* = dynamic_cast<splitNode*>(theNode);
bool isSplitNode = sNode != nullptr;
要不就
bool isSplitNode = dynamic_cast<splitNode*>(theNode);
如果您正确使用多态性,则不必这样做。
在您的基类中实现一个虚拟 GetType 方法并在子类中覆盖它。这是最有效的方法。
记住开闭原则。您应该利用多态性。
您可以使用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;
asplitNode
或leafNode
对象的指针,并且您调用p->foo()
,然后将调用适当版本的foo()
。这就是虚函数的全部意义所在。
另外,请参阅这个问题。
您可以使用运算符获取指向运行时多态对象的指针的基础类型typeid
。这是一个适合您描述的设计的示例:
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
它的作用几乎相同。
与typeid
在基类中存储某种形式的 type-id 并使用static_cast
. 尽管有这个警告,但它对于性能不是关键的代码(例如大多数代码)非常有用。
有一个它是什么类型的枚举成员,或者一个返回子节点数量的虚函数。就我个人而言,对于这种事情,我只会有一个带有枚举(或叶子的空子指针)的节点类。