У меня базовый класс:
class RedBlackTreeNode
{
// Interface is the same as the implementation
public:
RedBlackTreeNode* left;
RedBlackTreeNode* right;
RedBlackTreeNode* parent;
Color color;
TreeNodeData* data;
RedBlackTreeNode():
left(0),
right(0),
parent(0),
color(Black),
data(0)
{
}
// This method is to allow dynamic_cast
virtual void foo()
{
}
};
и производный от него:
class IndIntRBNode : public RedBlackTreeNode
{
public:
IndIntRBNode* left;
IndIntRBNode* right;
IndIntRBNode* parent;
IndexedInteger* data;
IndIntRBNode():
RedBlackTreeNode(),
left(0),
right(0),
parent(0),
color(Black),
data(0)
{
}
};
root () и rootHolder определены в классе RedBlackTree:
class RedBlackTree
{
public:
RedBlackTreeNode rootHolder;
RedBlackTreeNode* root()
{
return rootHolder.left;
}
...
}
Затем я пытаюсь привести к типу:
IndIntRBNode *x, *y, *z;
z = dynamic_cast<IndIntRBNode*>(root());
А «z» просто становится нулевым указателем, что означает, что приведение типа не удалось. Так что в этом плохого, как я могу исправить это, чтобы иметь возможность ссылаться на "z" как на указатель на IndIntRBNode?
Добавлено: инициализация rootHolder.left была чем-то вроде этого:
int n = atoi(line + i);
tree.clear();
int j = 0;
if (n > 100)
{
n = 100; // Maximum 100 nodes
}
while (j < n)
{
IndexedInteger num(j,j + 10);
RedBlackTreeNode* node;
int c = tree.search(&num, tree.root(), &node);
if (c != 0)
{ // if value is not in the tree
IndexedInteger* v = new IndexedInteger(num);
tree.insert(node, v, c);
++j;
}
}
Другими словами, он был инициализирован на первой итерации «while» методом «insert» таким образом:
void RedBlackTree::insert(
RedBlackTreeNode* parentNode,
TreeNodeData* v,
// If it's negative, then add as the left son, else as the right
int compare
)
{
assert(parentNode != 0 && compare != 0);
RedBlackTreeNode* x = new RedBlackTreeNode;
x->data = v;
x->parent = parentNode;
// If it's root
if (parentNode == &rootHolder)
{
// Then it must be black
x->color = Black;
}
else
{
// Leaf must be red
x->color = Red;
}
if (compare < 0)
{
// Insert the node as the left son
assert(parentNode->left == NULL);
parentNode->left = x;
}
else
{
// Insert the node as the right son
assert(parentNode != &rootHolder && parentNode->right == NULL);
parentNode->right = x;
}
++numNodes;
if (x != root())
{
rebalanceAfterInsert(x);
}
}
На самом деле проблема заключалась в том, что "insert" динамически создает RedBlackTreeNode, поэтому это не может быть IndIntRBNode. Я действительно неправильно инициализировал его, но тогда как я могу получить базовый класс и не писать всю его реализацию с нуля, просто чтобы изменить типы? Действительно ли мне нужно переопределить все "относящиеся к типу" методы в производном классе? Это кажется очень глупым, я думаю, должен быть другой способ - что-то с наследованием классов и приведением типов, не так ли?
rootHolder.left
? - person Kirill V. Lyadvinsky   schedule 14.08.2009