Я работаю над созданием двоичного дерева поиска с использованием классов типа интерфейса, которые мне были предоставлены. У меня есть класс BSTInterface, который состоит из чистых виртуальных функций. Он унаследован BST.h, который реализуется BST.cpp. BSTInterface выполняет функцию, называемую getRootNode(), которая возвращает NodeInterface * My NodeInterface.h - класс, состоящий из чистых виртуальных функций, которые унаследованы от Node.h, который реализован Node.cpp. В моей функции BST :: getRootNode() я могу вернуть узел *, или мне нужно вернуть NodeInterface *? Если мне нужно вернуть NodeInterface *, могу ли я просто установить NodeInterface * = Node *? Любая помощь, понимающая взаимосвязь между родительским и дочерним объектами, будет с благодарностью оценена. Спасибо огромное!Может ли указатели на дочерние объекты обрабатываться как указатели на родительские объекты?
ответ
В частности, для вашего случая, C++ допускает covariant return types. Это означает, что вы не можете вернуть только производный типа класса из унаследованного метода, но вы можете также объявить унаследованную функцию, чтобы вернуть devired типа:
class Node {};
class SpecialNode : public Node {};
class Base {
public:
virtual Node* getRootNode() = 0;
};
class Derived : public Base {
public:
virtual SpecialNode* getRootNode() override {
/* return a special node... */
}
};
В общем, вы можете присвоить указатель производного типа, указатель базового типа:
Node* node = new SpecialNode();
Обратите внимание, что это относится только к ссылкам и указателям. Вы не можете сделать то же самое с объектами, которые не объявлены как указатели или ссылки:
void someFunction (Node node) {}
SpecialNode sn;
// Causes "slicing" to occur
someFunction(sn);
Нарезка происходит при достаточно памяти выделяется только для базового класса, так как компилятор использует информацию о типе параметра узла через параметр (компилятор выделяет достаточно памяти только для Node
, а не SpecialNode
). Если были объявлены следующие
class Node {
private:
int x;
};
class SpecialNode : public Node {
private:
int y;
};
элемент данных «у» не будет присутствовать в узле передается someFunction
, так как он был «нарезанный». Обратите внимание, что это происходит только в прохождении по параметрам значения, а не по ссылке или по указателю. Для получения дополнительной информации см. object slicing.
Это очень полезно! огромное спасибо. –
Рад помочь. В качестве побочного примечания ссылки и указатели работают, потому что размер указателя (и ссылки, обычно реализованной с использованием указателя компилятором) всегда одинакового размера на той же машине. Поэтому указатель на базовый тип имеет тот же размер, что и указатель на производный тип. То же самое нельзя сказать о базовом и производном объекте: базовый объект имеет одно целое (x), а производный объект имеет два целых числа (x и y). Это основная причина, по которой указатели и ссылки не подвергаются обработке объектов. –
Вы можете вернуть указатель на производный класс в качестве указателя на базовый класс. Это основа полиморфизма. –